/**
 * 统一表格
 */
Vue.component('mk-table', {
    template: `
    <div class="mk-table">
        <el-form 
            ref="search"
            size="small"
            :inline="true"
            :model="search" 
            @submit.native.prevent>
            <el-form-item>
                <el-button
                    v-if="tree"
                    :icon="isExpand ? 'el-icon-arrow-down' : 'el-icon-arrow-right'"
                    @click="expandAll()">
                    <span class="title">{{isExpand ? '折叠' : '伸展'}}</span>
                </el-button>
                <el-button 
                    type="info"
                    icon="el-icon-refresh" 
                    @click="refresh()">
                    <span class="title">刷新</span>
                </el-button>
                <el-button 
                    v-if="saveAuthority" 
                    icon="el-icon-plus" 
                    type="primary" 
                    @click="drawerOpen()">
                    <span class="title">添加</span>
                </el-button>
                <el-button 
                    v-if="synchroAuthority"
                    size="small" 
                    icon="el-icon-warning-outline"
                    type="warning" 
                    @click="synchro()">
                    <span class="title">同步</span>
                </el-button>
                <el-popover
                    v-if="copyAuthority"
                    placement="top"
                    width="200"
                    v-model="copy.visible">
                    <el-form 
                        :model="copy.form" 
                        :rules="copy.rules" 
                        ref="copyForm">
                        <el-form-item prop="language">
                            <el-select 
                                v-model="copy.form.language"
                                placeholder="请选择语言" 
                                @change="languageChange()">
                                <template v-for="item in langAllow" :key="index">
                                    <el-option
                                        v-if="item.name !== language"
                                        :label="item.title"
                                        :value="item.name"
                                        filterable>
                                    </el-option>
                                </template>
                            </el-select>
                        </el-form-item>
                        <el-form-item v-if="copy.form.language != ''" prop="catalog_id">
                            <el-select 
                                v-model="copy.form.catalog_id" 
                                placeholder="请选择父级" 
                                v-loading="copy.catalogLoading"
                                filterable
                                :multiple="copyMultiple">
                                <el-option v-if="copyType === ''" label="最父级" value="">最父级</el-option>
                                <el-option
                                    v-for="(item, index) in copy.catalog"
                                    :key="index"
                                    :label="item.title"
                                    :value="item.id">
                                    <span v-html="item.treeString" class="mk-tree-name"></span>
                                    {{ item.title }}
                                </el-option>
                            </el-select>
                        </el-form-item>
                    </el-form>
                    <el-form-item>
                        <el-button type="primary" @click="copyRows()" :loading="copy.loading">确定</el-button>
                    </el-form-item>
                    <el-button
                        slot="reference" 
                        size="small" 
                        icon="el-icon-document-copy"
                        type="warning"
                        :disabled="rows.length === 0">
                        <span class="title">复制到其它语言</span>
                    </el-button>
                </el-popover>
                <el-button 
                    v-if="deleteAuthority" 
                    icon="el-icon-delete" 
                    type="danger" 
                    @click="remove()"
                    :disabled="rows.length > 0 ? false : true">
                    <span class="title">删除</span>
                </el-button>
                <slot name="header-button" v-bind="self"></slot>
            </el-form-item>
            <el-form-item prop="date" v-if="dateSearch">
                <el-date-picker
                    v-model="search.date"
                    type="daterange"
                    align="right"
                    unlink-panels
                    range-separator="至"
                    start-placeholder="开始日期"
                    end-placeholder="结束日期"
                    format="yyyy-MM-dd"
                    value-format="yyyy-MM-dd"
                    :picker-options="picker"
                    @change="toSearch()">
                </el-date-picker>
            </el-form-item>
            <el-form-item prop="keyword" v-if="keywordSearch">
                <el-input 
                    placeholder="根据关键词搜索" 
                    v-model="search.keyword" 
                    @keyup.enter.native="toSearch()">
                    <el-button 
                        slot="append" 
                        icon="el-icon-search" 
                        @click="toSearch()">
                    </el-button>
                </el-input>
            </el-form-item>
            <el-form-item prop="catalog_id" v-if="catalog.length > 0">
                <el-select 
                    v-model="search.catalog_id" 
                    placeholder="查看所有分类目录" 
                    @change="catalogChange()"
                    filterable>
                    <el-option label="全部分类" value=""></el-option>
                    <el-option
                        v-for="(item, index) in catalog"
                        :key="index"
                        :label="item.title"
                        :value="item.id">
                        <span v-html="item.treeString" class="mk-tree-name"></span>
                        {{ item.title }}
                    </el-option>
                </el-select>
            </el-form-item>
            <el-form-item prop="status" v-if="status.length > 0">
                <el-select 
                    v-model="search.status" 
                    placeholder="查看所有状态" 
                    @change="statusChange()">
                    <el-option label="全部状态" value=""></el-option>
                    <el-option
                        v-for="(item, index) in status"
                        :key="index"
                        :label="item.label"
                        :value="item.value">
                    </el-option>
                </el-select>
            </el-form-item>
            <slot name="header-search" v-bind="self"></slot>
        </el-form>
        <el-table
            ref="table"
            :class="{'sort-table': dropAuthority, tree: tree}"
            :data="table"
            :default-sort="{prop: search.prop, order: search.order}"
            v-loading="loading"
            @sort-change="sortChange"
            @selection-change="checkSelected"
            @select-all="selectAll()"
            @select="selectRow"
            :row-key="rowKey"
            :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
            :default-expand-all="isExpand"
            highlight-current-row>
            <el-table-column 
                type="selection" 
                width="55" 
                :selectable="selectableDisabled">
            </el-table-column>
            <el-table-column
                v-for="(item, index) in column"
                :key="index"
                :prop="item.prop" 
                :label="item.label" 
                :width="item.width"
                :sortable="item.sortable"
                v-if="typeof item.table === 'undefined' || item.table">
                <template slot-scope="scope">
                    <template v-if="item.type === 'text'">
                        <span v-text="scope.row[item.prop]"></span>
                    </template>
                    <template v-else-if="item.type === 'html'">
                        <span v-html="scope.row[item.prop]"></span>
                    </template>
                    <template v-else-if="item.type === 'image'">
                        <el-image 
                            :src="domain + scope.row[item.prop]" 
                            :preview-src-list="[domain + scope.row[item.prop]]"
                            :style="{width: typeof item.table === 'object' ? '25%' : ''}">
                            <div slot="error" class="image-slot">
                                <img class="error-image" :src="static + '/images/error.png'"/>
                            </div>
                        </el-image>
                    </template>
                    <template v-else-if="item.type === 'images'">
                        <mk-file-list-select 
                            v-model="scope.row[item.prop]" 
                            type="image">
                        </mk-file-list-select>
                    </template>
                    <template v-else-if="item.type === 'select'">
                        <el-select 
                            v-model="scope.row[item.prop]"
                            :disabled="tableAuthority(item, scope.row)"
                            :multiple="item.multiple"
                            :placeholder="item.placeholder"
                            filterable
                            @change="fieldUpdate(scope.row, item)">
                            <el-option
                                v-for="(val, key) in item.option"
                                :key="key"
                                :label="val[item.props.label]"
                                :value="val[item.props.value]">
                                <span v-if="item.tree" v-html="val.treeString" class="mk-tree-name"></span>
                                {{ val[item.props.label] }}
                            </el-option>
                        </el-select>
                    </template>
                    <template v-else-if="item.type === 'switch'">
                        <el-switch
                            v-model="scope.row[item.prop]"
                            :disabled="tableAuthority(item, scope.row)"
                            :active-value="1"
                            :inactive-value="0"
                            active-color="#13ce66"
                            @change="fieldUpdate(scope.row, item)">
                        </el-switch>
                    </template>
                    <template v-else-if="item.type === 'date'">
                        <el-date-picker
                            v-model="scope.row[item.prop]"
                            :disabled="tableAuthority(item, scope.row)"
                            type="date"
                            format="yyyy-MM-dd"
                            value-format="yyyy-MM-dd"
                            :placeholder="item.placeholder" 
                            @change="fieldUpdate(scope.row, item)">
                        </el-date-picker>
                    </template>
                    <template v-else-if="item.type === 'datetime'">
                        <el-date-picker
                            v-model="scope.row[item.prop]"
                            :disabled="tableAuthority(item, scope.row)"
                            type="datetime"
                            format="yyyy-MM-dd HH:mm:ss"
                            value-format="yyyy-MM-dd HH:mm:ss"
                            @change="fieldUpdate(scope.row, item)">
                        </el-date-picker>
                    </template>
                    <template v-else-if="item.type === 'datetimerange'">
                        <el-date-picker
                            v-model="scope.row[item.prop]"
                            :disabled="tableAuthority(item, scope.row)"
                            type="datetimerange"
                            start-placeholder="开始日期"
                            range-separator="至"
                            end-placeholder="结束日期"
                            format="yyyy-MM-dd HH:mm:ss"
                            value-format="yyyy-MM-dd HH:mm:ss"
                            @change="fieldUpdate(scope.row, item)">
                        </el-date-picker>
                    </template>
                    <template v-else>
                        <el-input 
                            v-model="scope.row[item.prop]"
                            :disabled="tableAuthority(item, scope.row)"
                            :placeholder="item.placeholder"
                            :ref="'reinput' + scope.$index + item.prop"
                            @focus="rename('reinput' + scope.$index + item.prop)"
                            @change="fieldUpdate(scope.row, item)">
                        </el-input>
                    </template>
                    <div v-if="typeof item.table === 'object'" class="scope-table" :class="'scope-table-' + item.type">
                        <div v-for="(s,k) in item.table">
                            {{typeof s.label !== 'undefined' &&  s.label !== '' ? s.label + '：' : ''}}
                            {{scope.row[s.prop]}}
                        </div>
                    </div>
                </template>
            </el-table-column>
            <el-table-column label="操作" width="200px" v-if="operateAuthority">
                <template slot-scope="scope">
                    <template v-if="typeof scope.row.operateClose ===  'undefined' ">
                        <el-tooltip content="拖放排序" placement="top" v-if="dropAuthority && ! scope.row.disabled">
                            <el-button 
                                size="mini" 
                                class="rank" 
                                type="info" 
                                icon="el-icon-rank" 
                                circle>
                            </el-button>
                        </el-tooltip>
                        <el-tooltip content="编辑" placement="top" v-if="updateAuthority && ! scope.row.disabled">
                            <el-button 
                                type="success" 
                                size="mini" 
                                icon="el-icon-edit" 
                                circle 
                                @click="drawerOpen(scope.row)">
                            </el-button>
                        </el-tooltip>
                        <el-tooltip content="删除" placement="top" v-if="deleteAuthority && ! scope.row.disabled">
                            <el-button 
                                type="danger" 
                                size="mini" 
                                icon="el-icon-delete" 
                                circle 
                                @click="remove(scope.row)">
                            </el-button>
                        </el-tooltip>
                        <el-tooltip content="复制" placement="top" v-if="saveAuthority && ! scope.row.disabled">
                            <el-button 
                                type="warning" 
                                size="mini" 
                                icon="el-icon-copy-document" 
                                circle 
                                @click="copyRow(scope.row)">
                            </el-button>
                        </el-tooltip>
                        <el-tooltip content="追加" placement="top" v-if="saveAuthority && tree">
                            <el-button 
                                type="primary" 
                                size="mini" 
                                icon="el-icon-plus" 
                                circle 
                                @click="pushRow(scope.row)">
                            </el-button>
                        </el-tooltip>
                        <slot name="public-button" v-bind:self="self" v-bind:row="scope.row"></slot>
                    </template>
                    <template v-else>{{scope.row.operateClose}}</template>
                </template>
            </el-table-column>
        </el-table>
        <el-pagination
            @size-change="pageSizeChange"
            @current-change="pageChange"
            :current-page="search.page"
            :page-size="search.pageSize"
            :page-sizes="pageSizes"
            :total="pageTotal"
            layout="total, sizes, prev, pager, next, jumper"
            background
            hide-on-single-page>
        </el-pagination>
        <mk-drawer-form
            v-model="drawer"
            :loading="drawerLoading"
            :title="isUpdate ? '编辑' : '添加'"
            @save="drawerSave()">
            <el-form
                :model="drawerData" 
                ref="drawerData" 
                :rules="drawerRules" 
                :label-width="labelWidth"
                :validate-on-rule-change="false">
                <el-tabs type="card" :class="{'not-exist': tabs.length === 1}">
                    <slot name="form-statr" v-bind="self"></slot>
                    <el-tab-pane 
                        v-for="(tab, tabK) in tabs" 
                        :name="String(tabK)"
                        :index="tabK">
                        <span slot="label"><i :class="tab.icon" v-if="typeof tab.icon !== 'undefined'"></i>{{tab.label}}</span>
                        <p class="website-title" v-if="typeof tab.title !=='undefined' && tab.title !== ''" v-html="tab.title"></p>
                        <template
                            v-for="(item, index) in tab.field"
                            :key="index">
                            <el-form-item 
                                v-show="formItemShow(item)"
                                :prop="item.prop"
                                :label-width="item.label == '' ? '0px' : ''"
                                :class="item.type">
                                <template slot="label">
                                    <div :style="{display: item.label == '' ? 'none' : 'inline-block'}">
                                        <el-tooltip placement="top" :content="item.prop">
                                            <div>{{item.label == '' ? '' : item.label}}：</div>
                                        </el-tooltip>
                                    </div>
                                </template>
                                <el-tooltip placement="top" :disabled="typeof item.tooltip === 'undefined'">
                                    <div slot="content">{{item.tooltip}}</div>
                                    <template v-if="item.type === 'text'">
                                        <div v-text="drawerData[item.prop]"></div>
                                    </template>
                                    <template v-else-if="item.type === 'html'">
                                        <div v-html="drawerData[item.prop]"></div>
                                    </template>
                                    <template v-else-if="typeof item.type === 'undefined' || item.type === 'input'">
                                        <el-input 
                                            v-model="drawerData[item.prop]"
                                            :disabled="formAuthority(item)"
                                            :placeholder="item.placeholder">
                                        </el-input>
                                    </template>
                                    <template v-else-if="item.type === 'textarea'">
                                        <el-input 
                                            v-model="drawerData[item.prop]" 
                                            type="textarea"
                                            :disabled="formAuthority(item)" 
                                            :placeholder="item.placeholder">
                                        </el-input>
                                    </template>
                                    <template v-else-if="item.type === 'select'">
                                        <el-select 
                                            v-model="drawerData[item.prop]" 
                                            :disabled="formAuthority(item)" 
                                            :placeholder="item.placeholder" 
                                            :multiple="item.multiple"
                                            filterable>
                                            <el-option v-if="typeof item.self !== 'undefined' && item.self" label="最父级" :value="0"></el-option>    
                                            <el-option
                                                v-if="typeof item.self !== 'undefined' && item.self"
                                                v-for="(val, key) in option"
                                                :key="key"
                                                :label="val[item.props.label]"
                                                :value="val[item.props.value]">
                                                <span v-html="val.treeString" class="mk-tree-name"></span>
                                                {{ val[item.props.label] }}
                                            </el-option>
                                            <el-option
                                                v-if="typeof item.self === 'undefined' || !item.self"
                                                v-for="(val, key) in item.option"
                                                :key="key"
                                                :label="val[item.props.label]"
                                                :value="val[item.props.value]">
                                                <span v-if="item.tree" v-html="val.treeString" class="mk-tree-name"></span>
                                                {{ val[item.props.label] }}
                                            </el-option>
                                        </el-select>
                                    </template>
                                    <template v-else-if="item.type === 'switch'">
                                        <el-switch
                                            v-model="drawerData[item.prop]"
                                            :disabled="formAuthority(item)" 
                                            :active-value="1"
                                            :inactive-value="0"
                                            active-color="#13ce66">
                                        </el-switch>
                                    </template>
                                    <template v-else-if="item.type === 'images'">
                                        <mk-file-list-select 
                                            v-model="drawerData[item.prop]" 
                                            :disabled="formAuthority(item)" 
                                            type="image">
                                        </mk-file-list-select>
                                    </template>
                                    <template v-else-if="item.type === 'image'">
                                        <mk-file-select 
                                            v-model="drawerData[item.prop]" 
                                            :disabled="formAuthority(item)">
                                        </mk-file-select>
                                    </template>
                                    <template v-else-if="item.type === 'file'">
                                        <mk-file-select 
                                            v-model="drawerData[item.prop]" 
                                            :disabled="formAuthority(item)"
                                            :type="typeof item.fileType === 'undefined' || item.fileType === '' ? 'file' : item.fileType">
                                        </mk-file-select>
                                    </template>
                                    <template v-else-if="item.type === 'link'">
                                        <mk-link 
                                            v-model="drawerData[item.prop]" 
                                            :disabled="formAuthority(item)">
                                        </mk-link>
                                    </template>
                                    <template v-else-if="item.type === 'editor'">
                                        <mk-editor 
                                            v-model="drawerData[item.prop]" 
                                            :disabled="formAuthority(item)">
                                        </mk-editor>
                                    </template>
                                    <template v-else-if="item.type === 'date'">
                                        <el-date-picker
                                            v-model="drawerData[item.prop]"
                                            :disabled="formAuthority(item)"
                                            type="date"
                                            format="yyyy-MM-dd"
                                            value-format="yyyy-MM-dd"
                                            :placeholder="item.placeholder" >
                                        </el-date-picker>
                                    </template>
                                    <template v-else-if="item.type === 'datetime'">
                                        <el-date-picker
                                            v-model="drawerData[item.prop]"
                                            :disabled="formAuthority(item)"
                                            type="datetime"
                                            format="yyyy-MM-dd HH:mm:ss"
                                            value-format="yyyy-MM-dd HH:mm:ss">
                                        </el-date-picker>
                                    </template>
                                    <template v-else-if="item.type === 'datetimerange'">
                                        <el-date-picker
                                            v-model="drawerData[item.prop]"
                                            :disabled="formAuthority(item)"
                                            type="datetimerange"
                                            start-placeholder="开始日期"
                                            range-separator="至"
                                            end-placeholder="结束日期"
                                            format="yyyy-MM-dd HH:mm:ss"
                                            value-format="yyyy-MM-dd HH:mm:ss">
                                        </el-date-picker>
                                    </template>
                                    <template v-else-if="item.type === 'field'">
                                        <div>
                                            <mk-field 
                                                v-model="drawerData[item.prop]" 
                                                :disabled="formAuthority(item)"
                                                :ifset="typeof item.ifset === 'undefined' || item.ifset === '' ? false : item.ifset"
                                                :label-width="labelWidth">
                                            </mk-field>
                                        </div>
                                    </template>
                                    <template v-else-if="item.type === 'parameter'">
                                        <mk-parameter 
                                            v-model="drawerData[item.prop]" 
                                            :disabled="formAuthority(item)">
                                        </mk-parameter>
                                    </template>
                                    <template v-else-if="item.type === 'tree'">
                                        <div>
                                            <el-checkbox 
                                                @change="drawerTreeCheckedAll(item)" 
                                                v-model="item.isChecked"
                                                label="全部选中" 
                                                size="mini" 
                                                border>
                                            </el-checkbox>
                                            <el-checkbox 
                                                @change="drawerTreeExpandAll(item)"
                                                v-model="item.isExpand"
                                                label="全部展开" 
                                                size="mini" 
                                                border>
                                            </el-checkbox>
                                            <el-tree
                                                :ref="item.prop"
                                                :data="item.tree"
                                                :disabled="formAuthority(item)"
                                                :render-content="drawerTreeContent"
                                                node-key="id"
                                                :props="item.props"
                                                :expand-on-click-node="false"
                                                show-checkbox
                                                check-on-click-node
                                                @check-change="drawerTreeChange(item)">
                                            </el-tree>
                                        </div>
                                    </template>
                                    <template v-else>
                                        <component
                                            v-model="drawerData[item.prop]"
                                            :disabled="formAuthority(item)"
                                            :is="item.type">
                                        </component>
                                    </template>
                                </el-tooltip>
                                <div style="color:#E6A23C" class="tips" v-html="item.tips"></div>
                            </el-form-item>
                        </template>
                    </el-tab-pane>
                    <slot name="form-tab" v-bind="self"></slot>
                </el-tabs>
            </el-form>
        </mk-drawer-form>
    </div>
    `,
    props: {
        url: {
            type: String,
            required: true
        },
        saveUrl: {
            type: String,
            default: ''
        },
        updateUrl: {
            type: String,
            default: ''
        },
        deleteUrl: {
            type: String,
            default: ''
        },
        dropUrl: {
            type: String,
            default: ''
        },
        synchroUrl: {
            type: String,
            default: ''
        },
        copyUrl: {
            type: String,
            default: ''
        },
        field: {
            type: Array,
            required: true
        },
        catalog: {
            type: Array,
            default: [],
        },
        status: {
            type: Array,
            default: [],
        },
        keywordSearch: {
            type: Boolean,
            default: true
        },
        dateSearch: {
            type: Boolean,
            default: true
        },
        tree: {
            type: Boolean,
            default: false
        },
        expand: {
            type: Boolean,
            default: false
        },
        labelWidth: {
            type: String,
            default: '100px'
        },
        rowKey: {
            type: String,
            default: 'id'
        },
        copyMultiple: {
            type: Boolean,
            default: true,
        },
        copyType: {
            type: String,
            default: ''
        },
        scene: {
            type: Array,
            default: []
        },
    },
    data() {
        return {
            self: this,
            rows: [],
            list: [],
            table: [],
            option: [],
            column: this.field,
            search: {
                keyword: '',
                date: '',
                catalog_id: '',
                status: '',
                prop: '',
                order: 'desc',
                page: 1,
                pageSize: 14,
            },
            pageSizes: [14, 50, 100, 200, 500, 1000, 3000],
            pageTotal: 0,
            loading: false,
            select: false,
            isExpand: this.expand,
            isUpdate: false,
            drawer: false,
            drawerData: {},
            drawerForm: {},
            drawerLoading: false,
            copy: {
                visible: false,
                loading: false,
                form: {
                    rows: [],
                    language: "",
                    catalog_id: "",
                },
                rules: {
                    language: [
                        {required: true, message: '不能为空', trigger: 'blur'}
                    ],
                },
                catalogLoading: false,
                catalogUrl: "catalog/copyListCatalog",
                catalog: [],
            },
            picker: {
                shortcuts: [{
                    text: '最近一周',
                    onClick(picker) {
                        const end = new Date();
                        const start = new Date();
                        end.setTime(start.getTime() + 3600 * 1000 * 24 * 1);
                        start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
                        picker.$emit('pick', [start, end]);
                    }
                }, {
                    text: '最近一个月',
                    onClick(picker) {
                        const end = new Date();
                        const start = new Date();
                        end.setTime(start.getTime() + 3600 * 1000 * 24 * 1);
                        start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
                        picker.$emit('pick', [start, end]);
                    }
                }, {
                    text: '最近三个月',
                    onClick(picker) {
                        const end = new Date();
                        const start = new Date();
                        end.setTime(start.getTime() + 3600 * 1000 * 24 * 1);
                        start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
                        picker.$emit('pick', [start, end]);
                    }
                }]
            },
        }
    },
     mounted () {
        this.drop();
    },
    created() {
        let form  = {};
        let prop  = "";
        let self  = this;
        self.column.forEach( function (item, index) {
            if (item.prop !== 'id'){
                form[item.prop]  = typeof item.default !== 'undefined' ? item.default : ''
            }
            if (typeof item.sortable !== 'undefined' && self.search.prop === '') {
                prop = item.prop
            }
        })
        self.drawerForm  = form;
        self.search.prop = prop;
        self.getData();
    },
    computed: {
        /**
         * 表单验证规则
         */
        drawerRules() {
            let rules = {};
            let self  = this;
            self.column.forEach( function (item, index) {
                let test = [];
                if (typeof item.rules !== 'undefined') {
                    // 添加时不能为空
                    if (typeof item.rules.saveRequired !== 'undefined' && self.isUpdate === false) {
                        test.push({required: true, message: '此处不能为空', trigger: 'blur'});
                    }
                    // 更新时不能为空
                    if (typeof item.rules.updateRequired !== 'undefined' && self.isUpdate) {
                        test.push({required: true, message: '此处不能为空', trigger: 'blur'});
                    }
                    if (typeof item.rules.required !== 'undefined') {
                        test.push({required: true, message: '此处不能为空', trigger: 'blur'});
                    }
                    if (typeof item.rules.min !== 'undefined') {
                        test.push({min: item.rules.min, message: '长度不能小于' + item.rules.min + '个字符', trigger: 'blur'});
                    }
                    if (typeof item.rules.max !== 'undefined') {
                        test.push({max: item.rules.max, message: '长度不能大于' + item.rules.min + '个字符', trigger: 'blur'});
                    }
                    if (typeof item.rules.type !== 'undefined') {
                        test.push({type: item.rules.type, message: '格式错误', trigger: 'blur'});
                    }
                    if (typeof item.rules.pattern !== 'undefined') {
                        test.push({pattern: item.rules.pattern, message: typeof item.rules.message !== 'undefined' ? item.rules.message : '验证错误', trigger: 'blur' });
                    }
                }
                if (typeof item.required !== 'undefined') {
                    let required = false;
                    item.required.forEach( function (val, key) {
                        required = self.drawerData[val.prop] === val.value;
                    })
                    required ? test.unshift({required: true, message: '此处不能为空', trigger: 'blur'}) : test.splice(0, 1);
                }
                rules[item.prop] = test;
            })
            return rules;
        },
        /**
         * 表单页
         */
        tabs() {
            let self = this;
            if (self.scene.length === 0) {
                return [{label: '基础信息', field: self.column}];
            } else {
                return this.scene;
            }
        },
        /**
         * 操作权限
         */
        operateAuthority() {
            if (this.saveUrl === '' && this.updateUrl === '' && this.deleteUrl === '') {
                return false;
            } else {
                return true;
            }
        },
        saveAuthority() {
            return authorityPath.indexOf(this.saveUrl) !== -1;
        },
        updateAuthority() {
            return authorityPath.indexOf(this.updateUrl) !== -1;
        },
        deleteAuthority() {
            return authorityPath.indexOf(this.deleteUrl) !== -1;
        },
        dropAuthority() {
            return authorityPath.indexOf(this.dropUrl) !== -1
        },
        synchroAuthority() {
            return authorityPath.indexOf(this.synchroUrl) !== -1 && language !== langDefault;
        },
        copyAuthority() {
            return authorityPath.indexOf(this.copyUrl) !== -1 && authorityPath.indexOf(this.copy.catalogUrl) !== -1
        }
    },
    methods: {
        /**
         * 获取数据
         */
        getData() {
            let self     = this;
            self.loading = true;
            request.post(self.url, self.search, function(res) {
                if (res.status === 'success') {
                    self.list      = JSON.parse(JSON.stringify(res.data));
                    self.table     = self.tree ? tree.convert(res.data) : res.data;
                    self.pageTotal = res.count;
                    self.$emit('refresh', {self: self, res: res});
                } else {
                    self.$message({ showClose: true, message: res.message, type: res.status});
                }
                self.loading = false;
            });
        },
        /**
         * 表格input重命名
         */
        rename(ref) {
            this.$nextTick(()=>{
                let el = this.$refs[ref][0];
                el.select();
            });
        },
        /**
         * 表格操作权限
         */
        tableAuthority(item, row) {
            return item.update === false || item.update === row[item.prop] || ! this.updateAuthority || item.disabled || row.disabled;
        },
        /**
         * 表单操作权限
         */
        formAuthority(item) {
            return this.isUpdate && item.update === false || item.update === this.drawerData[item.prop]
        },
        /**
         * 保存数据
         */
        save(refresh = true) {
            let self = this;
            if(self.$listeners['save']) {
                self.$emit('save', {self: self});
            } else {
                let url  = self.isUpdate ? self.updateUrl : self.saveUrl;
                self.drawerLoading = true;
                request.post(url, self.drawerData, function(res){
                    self.drawerLoading = false;
                    if (res.status === 'success') {
                        self.drawer = false;
                        if (refresh) self.getData();
                    } else {
                        self.$message({ showClose: true, message: res.message, type: res.status});
                        self.getData();
                    }
                });
            }
        },
        /**
         * 字段更新
         */
        fieldUpdate(row, item) {
            this.drawerData = row;
            this.isUpdate = true;
            this.save(typeof item.refresh !== 'undefined' && item.refresh);
        },
        /**
         * 向父级追加
         */
        pushRow(row) {
            let arr = JSON.parse(JSON.stringify(this.drawerForm));
            arr.pid  = row.id;
            this.drawerOpen(arr);
            this.isUpdate = false;
        },
        /**
         * 复制
         */
        copyRow(row) {
            let arr = JSON.parse(JSON.stringify(row));
            delete(arr['id']);
            this.drawerOpen(arr);
            this.isUpdate = false;
        },
        /**
         * 复制到其它语言
         */
        copyRows() {
            let self = this;
            self.$refs.copyForm.validate((valid) => {
                if (valid) {
                    self.copy.loading = true;
                    self.copy.form.rows = self.rows;
                    request.post(self.copyUrl, self.copy.form, function(res) {
                        self.copy.loading = false;
                        self.copy.visible = false;
                        self.$message({ showClose: true, message: res.message, type: res.status});
                    });
                } else {
                    return false;
                }
            })
        },
        /**
         * 同步主语言数据
         */
        synchro() {
            let self = this;
            self.$confirm('系统会删除当前语言数据，确定同步吗？', '', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {
                request.post(self.synchroUrl, {}, function(res) {
                    if (res.status === 'success') {
                        self.getData();
                    } else {
                        self.$message({ showClose: true, message: res.message, type: res.status});
                    }
                });
            }).catch(() => {});
        },
        /**
         * 删除
         */
        remove(row = "") {
            let self = this;
            if(self.$listeners['remove']) {
                self.$emit('remove', {self: self, rows: row === "" ? self.rows : [row]});
            } else {
                let ids  = row === "" ? common.arrayColumn(self.rows,'id') : [row.id]; 
                self.$confirm('确定删除数据吗？', '', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning'}).then(() => {
                    request.post(self.deleteUrl, {'ids': ids}, function(res){
                        if (res.status === 'success') {
                            self.getData();
                        } else {
                            self.$message({ showClose: true, message: res.message, type: res.status});
                        }
                    });
                }).catch(() => {});
            }
        },
        /**
         * 拖动排序
         */
        drop(){
            let self = this;
            if (self.dropAuthority) {
                let el = self.$refs.table.$el.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]
                self.sortable = Sortable.create(el,{
                    animation: 300,
                    forceFallback: true,
                    delay: 20,
                    handle: '.rank',
                    onEnd: evt => {
                        if (evt.newIndex !== evt.oldIndex) {
                            if(self.$listeners['drop']) {
                                self.$emit('drop', {self: self, evt: evt});
                            } else {
                                let targetRow = self.table.splice(evt.oldIndex, 1)[0];
                                // 位置调换
                                self.table.splice(evt.newIndex, 0, targetRow);
                                // 计算当前index
                                let index = (self.search.pageSize * (self.search.page-1)) + evt.newIndex;
                                // 计算当前排序
                                let sort = self.pageTotal - index;
                                self.loading = true;
                                request.post(self.dropUrl, {sort: sort, row: self.table[evt.newIndex]}, function(res){
                                    if (res.status !== 'success') {
                                        self.$message({ showClose: true, message: res.message, type: res.status});
                                    }
                                    self.getData();
                                });
                            }
                        }
                    }
                })
            }
        },
        /**
         * 选中所有行，只有树形结构需要这样处理
         */
        selectAll() {
            let self = this;
            let table = self.$refs.table;
            self.select = self.select ? false : true;
            self.table.forEach(function (item, index){
                table.toggleRowSelection(item, self.select);
            });
        },
        /**
         * 选中行，只有树形结构需要这样处理
         */
        selectRow(selection, row, status = "") {
            if (row.children) { //只对有子节点的行响应
                row.isChecked = status === "" ? !row.isChecked :status;
                row.children.map((item) => {
                    this.$nextTick(() => {
                        this.$refs.table.toggleRowSelection(item, row.isChecked);
                    });
                    item.isChecked = row.isChecked;
                    this.selectRow({}, item, row.isChecked);
                });
            }
        },
        /**
         * 折叠/展开行
         */
        expandAll() {
            let $table = this.$refs.table;
            this.isExpand = !this.isExpand;
            this.table.forEach(function (item, index){
                $table.toggleRowExpansion(item, this.isExpand);
            });
        },
        /**
         * 选中行
         */
        checkSelected(rows) {
            this.rows = rows;
        },
        /**
         * 行不可选中
         */
        selectableDisabled(row, index) {
            return ! row.disabled;
        },
        /**
         * 语言分类请求
         */
        languageChange() {
            let self = this;
            self.copy.catalogLoading = true;
            request.post(self.copy.catalogUrl, {lang: self.copy.form.language, type: self.copyType}, function(res) {
                self.copy.catalogLoading = false;
                self.copy.catalog = tree.convertString(res.data);
            });
        },
        /**
         * 刷新
         */
        refresh() {
            this.$refs.search.resetFields();
            this.search = Object.assign({}, this.search, {page: 1});
        },
        /**
         * 搜索
         */
        toSearch() {
            this.search = Object.assign({}, this.search, {page: 1});
        },
        /**
         * 分类改变
         */
        catalogChange() {
            this.search = Object.assign({}, this.search, {page: 1});
        },
        /**
         * 状态改变
         */
        statusChange() {
            this.search = Object.assign({}, this.search, {page: 1});
        },
        /**
         * 排序改变
         */
        sortChange(v) {
            this.search = Object.assign({}, this.search, {page: 1 ,prop: v.prop , order: v.order});
        },
        /**
         * 分页个数改变时
         * @param  {Number} val 每页数量
         */
        pageSizeChange(val) {
            this.search = Object.assign({}, this.search, {page: 1 ,pageSize: val});
        },
        /**
         * 分页改变时
         * @param  {String} val 当前页
         */
        pageChange(val) {
            this.search = Object.assign({}, this.search, {page: val});
        },
        /**
         * 表单显示
         */
        formItemShow(item) {
            let self = this;
            if (item.form === false || item.prop === 'id') {
                return false;
            } else {
                if (typeof item.form === 'object') {
                    let show = true;
                    item.form.forEach(function (val, key) {
                        if (self.drawerData[val.prop] !== val.value) {
                            show = false;
                        }
                    });
                    return show;
                }
                return true;
            }
        },
        /**
         * 抽屉打开
         */
        drawerOpen(row = "") {
            this.isUpdate = row !== "";
            this.drawerData = row === "" ? JSON.parse(JSON.stringify(this.drawerForm)) : JSON.parse(JSON.stringify(row));
            this.drawer = true;
        },
        /**
         * 抽屉保存
         */
        drawerSave() {
            let self = this;
            self.$refs.drawerData.validate((valid) => {
                if (valid) {
                    self.save();
                } else {
                    return false;
                }
            });
        },
        /**
         * 抽屉的菜单权限全选处理
         */
        drawerTreeCheckedAll(item){
            let keys = [];
            if(item.isChecked === true) keys = common.arrayColumn(item.list, 'id');
            this.$refs[item.prop][0].setCheckedKeys(keys);
        },
        /**
         * 抽屉的菜单权限展开/折叠
         */
        drawerTreeExpandAll(item){
            let self = this;
            let keys = common.arrayColumn(item.list, 'id');
            keys.forEach(function(val, key){
                self.$refs[item.prop][0].store.nodesMap[val].expanded = item.isExpand;
            })
            self.$nextTick(()=>{
                self.drawerTreeCss();
            })
        },
        /**
         * 抽屉的菜单权限样式处理
         */
        drawerTreeContent(h, { node, data, store }) {
            if (data.pid === 0 ) {
                var classname = "";
            } else {
                var classname = typeof data.children === "undefined" ||  data.children.length === 0 ? "levelname" :"";
            }
            return h("p", { class: classname }, node.label );
        },
        /**
         * 抽屉的菜单权限样式处理
         */
        drawerTreeCss() {
            var levelName = document.getElementsByClassName("levelname");
            for (var i = 0; i < levelName.length; i++) {
                levelName[i].parentNode.style.cssFloat = "left";
                levelName[i].parentNode.style.styleFloat = "left";
                levelName[i].parentNode.style.paddingLeft = "18px";
            }
        },
        /**
         * 抽屉的菜单权限状态改变
         */
        drawerTreeChange(item) {
            let roleSel = this.$refs[item.prop][0].getCheckedKeys();
            let rolePar = this.$refs[item.prop][0].getHalfCheckedKeys();
            let roleArr = roleSel.concat(rolePar);
            this.drawerData[item.prop] = roleArr.join(',');
        }
    },
    watch: {
        search() {
            this.getData();
        },
        drawer(v) {
            if(v){
                let self = this;
                self.$nextTick(()=>{
                    // 当前结构是树形
                    self.column.forEach( function (item, index) {
                        if (item.type === 'tree') {
                            self.$refs[item.prop][0].setCheckedKeys([]);
                            self.$refs[item.prop][0].setCheckedKeys(self.drawerData[item.prop].split(','));
                        }
                    });
                    // 当前本身父级
                    self.option = [];
                    self.list.forEach( function (val, key) {
                        if (val.id !== self.drawerData.id && typeof val.operateClose ===  'undefined') {
                            self.option.push(val);
                        }
                    });
                    self.option = tree.convertString(self.option);
                })
            } else {
                this.$refs.drawerData.clearValidate();
            }
        },
    }
});
/**
 * 抽屉表单
 */
Vue.component('mk-drawer-form', {
    template: `
    <el-drawer
        class="mk-drawer-form"
        :visible.sync="drawer"
        :with-header="false"
        size="100%">
        <div class="mk-drawer-warp">
            <el-page-header
                @back="drawer=false" 
                :content="title">
                <template v-slot:title>Esc键返回</template>
            </el-page-header>
            <div class="mk-card-tabs mk-drawer-main" :style="{'height':drawerHeight}">
                <slot></slot>
            </div>
            <div class="mk-drawer-footer">
                <el-button 
                    type="primary" 
                    size="medium" 
                    icon="el-icon-refresh-right"
                    @click="$emit('save')" 
                    :loading="loading">
                    保 存
                </el-button>
                <el-button size="medium" @click="drawer=false">返 回</el-button>
            </div>
        </div>
    </el-drawer>
    `,
    props: {
        value: {
            type: Boolean,
            default: false,
        },
        title: {
            type: String,
            default: '',
        },
        loading:{
            type: Boolean,
            default: false,
        },
    },
    data() {
        return {
            drawer: this.value,
            drawerHeight: window.innerHeight - 170 + 'px',
        }
    },
    mounted () {
        window.onresize = () => {
            return (() => {
                this.drawerHeight = window.innerHeight - 170 + 'px';
            })()
        }
    },
    watch: {
        value(v) {
            this.drawer = v;
        },
        drawer(v) {
            this.$emit('input', v);
        }
    }
});
/**
 * 登录表单
 */
Vue.component('mk-login-form', {
    template: `
    <el-form 
        class="mk-login-form" 
        :model="loginForm" 
        :rules="rules" 
        ref="loginForm"
        @submit.native.prevent>
        <template v-if="captchaShow">
            <div class="mk-captcha-title">机器验证</div>
            <el-form-item v-if=" captcha !== '' " prop="captcha">
                <img 
                    class="mk-captcha-img" 
                    :src="captcha" 
                    @click="getCaptcha()" />
                <el-input 
                    class="mk-captcha-code" 
                    v-model="loginForm.captcha" 
                    placeholder="请输入上方的图形验证码"
                    @keyup.enter.native="submitForm()">
                </el-input>
            </el-form-item>
            <el-button
                :disabled="loginForm.captcha.length === 4 ? false : true"
                class="login-btn" 
                @click="submitForm()" 
                :loading="loading" 
                plain>
                验证
            </el-button>
        </template>
        <template v-else>
            <el-form-item>
                账号：admin，密码：123456
            </el-form-item>
            <el-form-item prop="loginAccount">
                <el-input 
                    v-model="loginForm.loginAccount" 
                    prefix-icon="el-icon-user" 
                    placeholder="请输入账号/邮箱号"
                    @keyup.enter.native="getCaptcha()">
                </el-input>
            </el-form-item>
            <el-form-item prop="loginPassword">
                <el-input 
                    v-model="loginForm.loginPassword" 
                    prefix-icon="el-icon-key" 
                    placeholder="请输入密码" 
                    show-password
                    @keyup.enter.native="getCaptcha()">
                </el-input>
            </el-form-item>
            <el-form-item prop="checked">
                <el-checkbox v-model="loginForm.checked">两周内自动登录</el-checkbox>
            </el-form-item>
            <el-button 
                class="login-btn" 
                @click="getCaptcha()" 
                :loading="loading"
                plain>
                登录
            </el-button>
            <div class="regOrPwd">
                <a href="password" class="password">已有账号，忘记密码？</a>
            </div>
        </template>
    </el-form>`,
    data() {
        return {
            loading: false,
            storageTime: 240*60*60*1000,
            captcha: "",
            captchaShow: false,
            loginForm: {
                loginAccount: "",
                loginPassword: "",
                captcha: "",
                checked: false,
            },
            rules: {
                loginAccount: [
                    { required: true, message: '请输入账号', trigger: 'blur' },
                ],
                loginPassword: [
                    { required: true, message: '请输入密码', trigger: 'blur' },
                ],  
                captcha: [
                    { min: 4, message: '验证码长度有误', trigger: 'blur' }
                ],  
            },
        }
    },
    methods: {
        /**
         * 准备登录
         */
        getCaptcha() {
            let self = this;
            request.post('login/isNeedVerification', {}, function(res){
                let url = admin_url('login/verify');
                let str = url.indexOf('?') === -1 ? '?' : '&';
                self.captcha = res == 1 ? url + str + Math.random() : '';
                self.$refs.loginForm.validate((valid) => {
                    if (valid) {
                        if (self.captcha !== '') {
                            self.captchaShow  = true;
                        } else {
                            self.submitForm();
                        }
                    } else {
                        return false;
                    }
                });
            })
        },
        /**
         * 登录
         */
        submitForm() {
            let self = this;
            self.loading = true;
            request.post('login/index', self.loginForm, function (res){
                self.loading = false;
                self.$message({ showClose: true, message: res.message, type: res.status});
                if(res.status === 'success'){
                    self.$emit('success-login', res.url);
                } else {
                    self.captchaShow       = false;
                    self.loginForm.captcha = "";
                }
            })
        },
    },
});
/**
 * 登录弹窗
 */
Vue.component('mk-login-dialog', {
    template: `
    <el-dialog
        top="30px"
        title="登录"
        width="450px"
        class="mk-login-dialog"
        :visible.sync="loginDialog"
        :close-on-click-modal="false"
        center>
            <div class="mk-aside-logo-warp"><div></div></div>
            <mk-login-form @success-login="success($event)"></mk-login-form>
    </el-dialog>`,
    data() {
        return store.state
    },
    methods: {
        success(res) {
            this.loginDialog = false;
            // location.href = url;
        }
    },
});
/**
 * 通用数组
 */
Vue.component('mk-array', {
    template: `
    <div class="mk-array" ref="mkArray">
        <el-table :data="table" row-key="id" border>
            <el-table-column prop="title" label="标题">
                <template slot-scope="scope">
                    <el-input type="text" v-model="scope.row.title" size="small"></el-input>
                </template>
            </el-table-column>
            <el-table-column prop="value" label="内容">
                <template slot-scope="scope">
                    <el-input v-model="scope.row.value" size="small"></el-input>
                </template>
            </el-table-column>
            <el-table-column v-for="(item, index) in field" :prop="item" :key="index">
                <template slot="header" slot-scope="scope">
                    <el-tooltip :content="'变量：' + item.name" placement="top-start">
                        <span>自定义字段</span>
                    </el-tooltip>
                    <el-button style="float:right" type="danger" icon="el-icon-minus" size="mini" circle @click="delField(index)"></el-button>
                </template>
                <template slot-scope="scope">
                    <el-input 
                        v-if="item.type === 'string'"
                        v-model="scope.row[item.name]" 
                        size="small">
                    </el-input>
                    <mk-file-select 
                        v-if="item.type === 'image' || item.type === 'file'"
                        v-model="scope.row[item.name]" 
                        :type="item.type">
                    </mk-file-select>
                    <mk-link 
                        v-if="item.type === 'link'"
                        v-model="scope.row[item.name]" 
                        size="small">
                    </mk-link>
                </template>
            </el-table-column>
            <el-table-column width="150">
            <template slot="header" slot-scope="scope">
                <el-button
                    v-if="type === 'array'"
                    type="primary" 
                    @click="dialog = true"
                    size="mini">
                    新增字段
                </el-button>
                <span v-else>操作</span>
            </template>
            <template slot-scope="scope">
                <el-button
                    class="mk-sortable-rank"
                    icon="el-icon-rank"
                    size="mini"
                    circle>
                </el-button>
                <el-button
                    type="primary"
                    icon="el-icon-plus"
                    size="mini"
                    @click="addArray(scope.$index)"
                    circle>
                </el-button>
                <el-button
                    type="danger" 
                    icon="el-icon-delete"
                    size="mini"
                    @click="delArray(scope.$index)"
                    circle>
                </el-button>
            </template>
            </el-table-column>
        </el-table>
        <el-dialog
            top="16px"
            :visible.sync="dialog"
            :before-close="fieldFormClose"
            :close-on-click-modal="false"
            width="500px"
            center
            append-to-body>
            <el-form
                @submit.native.prevent 
                :model="fieldForm" 
                :rules="fieldFormRules" 
                ref="fieldForm" 
                label-width="100px">
                <el-form-item label="字段类型" prop="type">
                    <el-select v-model="fieldForm.type" size="small">
                        <el-option
                            v-for="item in fieldTypeList"
                            :key="item.value"
                            :label="item.label"
                            :value="item.value">
                        </el-option>
                    </el-select>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="dialog = false" size="small">取 消</el-button>
                <el-button type="primary" @click="addField()" size="small">确 定</el-button>
            </span>
        </el-dialog>
        <el-button 
            style="margin-top:20px"
            type="primary" 
            @click="addArray()"
            size="small">
            新增行
        </el-button>
    </div>
    `,
    props: {
        value: {
            type: Array,
            default: [],
        },
        type: {
            type: String,
            default: '',
        },
    },
    data() {
        return {
            table: this.value,
            field: [],
            rIndex: 0,
            dialog: false,
            fieldForm: {
                type: 'string',
            },
            fieldTypeList: [
                {label: '字符串', value: 'string'},
                {label: '链接', value: 'link'},
                {label: '图片', value: 'image'},
                {label: '文件', value: 'file'},
            ],
            fieldFormRules: {
                type: [
                    { required: true, message: '请选择字段类型', trigger: 'blur' },
                ],
            }
        }
    },
    mounted() {
        this.rowDrop()
    },
    created () {
        this.initField();
    },
    methods: {
        /**
         * 初始化字段
         */
        initField() {
            let self = this;
            self.field = [];
            if (self.table === '') self.table = [];
            if (self.type === 'array') {
                if (typeof self.table[0] !== 'undefined') {
                    let field = Object.keys(self.table[0]);
                    field.forEach(function (item, index) {
                        if (item.indexOf("value_") !== -1) {
                            let fieldArr = item.split('_');
                            let reNumber = parseInt(fieldArr[2]);
                            self.rIndex  = reNumber > self.rIndex ? reNumber : self.rIndex;
                            self.field.push({name: item, type: fieldArr[1]});
                        }
                    })
                }
            }
        },
        /**
         * 行拖拽
         */
        rowDrop() {
            let self  = this;
            self.$nextTick(() => {
                let tbody = self.$refs.mkArray.querySelector('.el-table__body-wrapper tbody');
                Sortable.create(tbody, {
                    forceFallback: true,
                    animation: 300,
                    handle: ".mk-sortable-rank",
                    onEnd({ newIndex, oldIndex }) {
                        let currRow = self.table.splice(oldIndex, 1)[0]
                        self.table.splice(newIndex, 0, currRow)
                    },
                })
            });
        },
        // 关闭自定义字段弹出
        fieldFormClose() {
            this.$refs.fieldForm.resetFields();
            this.dialog = false;
        },
        /**
         * 添加数组
         * @param {String} index 下标
         */
        addArray(index = "") {
            // 取出最大的id
            var maxId = 1;
            this.table.forEach(function (item, index){
                if (parseInt(item.id) >= maxId){
                    maxId = parseInt(item.id) + 1;
                }
            })
            // 初始值
            let data  = {"id": maxId,"title":"", "value":""};
            this.field.forEach(function(item, index) {
                data[item.name] = "";
            });
            // 添加
            if(index === ""){
                this.table.push(data);
            }else{
                this.table.splice(index+1,0,data);
            }
        },
        /**
         * 删除数组
         * @param {String} index 下标
         */
        delArray(index){
            this.table.splice(index,1);
        },
        /**
         * 新增字段
         */
        addField() {
            this.$refs.fieldForm.validate((valid) => {
                if (valid) {
                    this.rIndex ++;
                    let self = this;
                    let name = 'value_' + this.fieldForm.type + '_' + self.rIndex;
                    self.field.push({name: name, type: this.fieldForm.type});
                    self.table.forEach(function(item, index) {
                        self.$set(item, name, "");
                    });
                    this.fieldFormClose();
                } else {
                    return false;
                }
            });
        },
        /**
         * 删除字段
         * @param {String} index 下标
         */
        delField(index) {
            let self = this;
            let prop = self.field[index]['name'];
            self.field.splice(index,1);
            self.table.forEach(function(item, index) {
                self.$delete(item, prop);
            });
        },
    },
    watch: {
        table(v) {
            this.$emit('input', v);
        },
        value(v) {
            this.table = v;
            this.initField();
        }
    }
});
/**
 * 文件列表
 */
Vue.component('mk-file-list', {
    template: `
    <div class="mk-file-list">
        <el-tabs
        class="mk-files-tabs"
        v-model="fileTypeIndex"
        @tab-click="changeFileType"
        tab-position="left">
            <el-tab-pane
                v-for="(item, index) in fileTypeList"
                :key="index"
                :name="String(index)" 
                :label="item.label">
                <div class="files-header">
                    <el-tooltip content="退后" placement="bottom">
                        <el-button 
                            class="icon-button" 
                            size="small" 
                            icon="el-icon-back" 
                            @click="back()"
                            :disabled="breadcrumb.length  === 1 && fileSearch.keyword === ''"
                            plain>
                        </el-button>
                    </el-tooltip>
                    <el-breadcrumb separator-class="el-icon-arrow-right">
                        <el-breadcrumb-item v-for="(item, index) in breadcrumb" :key="index">
                            <span class="el-breadcrumb-item-span" @click="clickBreadcrumb(index)">{{item.title}}</span>
                        </el-breadcrumb-item>
                    </el-breadcrumb>
                    <el-input 
                        placeholder="搜索全部资源文件"
                        v-model="fileSearch.keyword"
                        size="small" 
                        class="input-keyword" 
                        @keyup.enter.native="searchKeyword">
                        <el-button slot="append" icon="el-icon-search" @click="searchKeyword"></el-button>
                    </el-input>
                </div>
                <div class="files-header">
                    <el-button
                        size="small" 
                        icon="el-icon-refresh-right" 
                        @click="refresh()" 
                        plain>
                        刷新
                    </el-button>
                    <el-upload
                        v-show="addAuthority && fileTypeName !== 'recycle'"
                        class="file-upload"
                        :accept="acceptList[fileTypeName]"
                        :show-file-list="false"
                        :action="admin_url(addUrl)"
                        :data="{pid: fileSearch.pid, theme: typeof theme != 'undefined' ? theme : ''}"
                        :before-upload="beforeUpload"
                        :on-progress="progressUpload"
                        :on-success="successUpload"
                        :on-error="errorUpload"
                        multiple>
                        <el-button size="small" icon="el-icon-upload2" plain>上传</el-button>
                    </el-upload>
                    <el-button
                        v-show="addFolderAuthority && fileTypeName !== 'recycle'" 
                        :loading="addFolderLoading"
                        size="small" 
                        icon="el-icon-folder-add" 
                        @click="addFolder()" 
                        plain>
                        新建文件夹
                    </el-button>
                    <mk-watermark v-if="item.name === 'image'"></mk-watermark>
                    <el-button 
                        v-show="delOrRecycleAuthority && fileTypeName === 'recycle'"
                        size="small" 
                        icon="el-icon-delete" 
                        @click="clear()"
                        plain>
                        清空回收站
                    </el-button>
                    <el-button
                        v-show="recycleAuthority && fileTypeName === 'recycle'"
                        size="small" 
                        icon="el-icon-folder-checked" 
                        :disabled="rows.length == 0"
                        @click="reduction()"
                        plain>
                        文件还原
                    </el-button>
                    <el-button 
                        v-show="delOrRecycleAuthority && fileType === 'all'"
                        size="small" 
                        icon="el-icon-delete" 
                        :disabled="rows.length == 0"
                        @click="del()"
                        plain>
                        {{fileTypeName !== 'recycle' ? '删除' : '永久删除'}}
                    </el-button>
                    <el-button
                        v-show="pasteAuthority && fileTypeName !== 'recycle' && fileType === 'all'" 
                        size="small"
                        icon="el-icon-document-copy"
                        :disabled="rows.length == 0"
                        @click="shear()"
                        plain>
                        剪切
                    </el-button>
                    <el-button
                        v-show="pasteAuthority && fileTypeName !== 'recycle' && fileType === 'all'"
                        size="small"
                        :disabled="pasteType === ''"
                        @click="paste()"
                        :loading="pasteLoading"
                        plain>
                        粘贴
                    </el-button>
                </div>
                <el-table
                    class="files-warp" 
                    v-infinite-scroll="pageChange"
                    infinite-scroll-immediate="false"
                    infinite-scroll-distance="100"
                    :style="{height: height}"
                    :class="fileType === 'all' ? '' : 'popup-mode'"
                    :ref="'table' + index"
                    :data="fileNowList"
                    @row-click="clickSelected"
                    @selection-change="checkSelected"
                    @select="selectedFile"
                    :default-sort="{prop: sortable.prop, order: sortable.order}"
                    @sort-change="sortChange">
                    <el-table-column type="selection" width="55" :selectable="checkDisabled"></el-table-column>
                    <el-table-column prop="title" label="文件名" width="280" sortable="custom">
                        <div 
                            @click.stop="see(scope.row, scope.$index)"
                            class="file-title-cover" 
                            slot-scope="scope">
                            <el-image 
                                style="display:none"
                                :src="domain + scope.row.url"
                                :ref="'preview' + scope.$index" 
                                :preview-src-list="scope.row.type === 'image' ? srcList(scope.$index) : []">
                            </el-image>
                            <img
                                v-if="scope.row.cover"
                                class="file-cover" 
                                :class="scope.row.shear ? 'shear-row' : ''"
                                :src="domain + scope.row.cover"/>
                            <el-progress 
                                v-else
                                type="circle" 
                                :percentage="scope.row.percentage">
                            </el-progress>
                            <input
                                class="file-title"
                                :class="{'file-title-disabled':scope.row.rename}"
                                :disabled="scope.row.rename"
                                v-model="scope.row.title" 
                                size="mini"
                                :ref="'title' + scope.row.id"
                                @change="changeRename(scope.row)"
                                @blur="blurRename()">
                            </input>
                        </div>
                    </el-table-column>
                    <el-table-column prop="create_time" label="修改时间" width="140" sortable="custom"></el-table-column>
                    <el-table-column prop="type" label="类型" width="100" sortable="custom">
                        <template slot-scope="scope">{{scope.row.typeName}}</template>
                    </el-table-column>
                    <el-table-column prop="size" label="大小" width="100" sortable=" custom">
                        <template slot-scope="scope">
                            <div v-if="scope.row.folder === 1"
                                class="count-size"
                                @click.stop="countSize(scope.row)">
                                <i class="el-icon-loading" v-show="scope.row.countSizeLoading"></i>
                                {{countSizeAuthority === false ? "" : scope.row.sizeName}}
                            </div>
                            <div v-else>{{scope.row.sizeName}}</div>
                        </template>
                    </el-table-column>
                    <el-table-column label="操作">
                        <template slot-scope="scope">
                            <span
                                class="mk-operation-btn"
                                v-show="scope.row.status === 1 || scope.row.folder === 0"
                                @click.stop="see(scope.row, scope.$index)">
                                {{scope.row.folder == 0 ? '预览' : '打开'}}
                            </span>
                            <span
                                class="mk-operation-btn"
                                v-show="recycleAuthority && scope.row.status == 0 && fileType === 'all'" 
                                @click.stop="reduction(scope.row)">
                                还原
                            </span>
                            <span
                                class="mk-operation-btn"
                                v-show="pasteAuthority && scope.row.status === 1 && fileType === 'all'" 
                                @click.stop="shear(scope.row)">
                                剪切
                            </span>
                            <span
                                class="mk-operation-btn"
                                v-show="editAuthority && scope.row.status === 1" 
                                @click.stop="clickRename(scope.row)">
                                重命名
                            </span>
                            <span
                                class="mk-operation-btn"
                                v-show="delOrRecycleAuthority"
                                @click.stop="del(scope.row)">
                                {{scope.row.status === 1 ? '删除' : '永久删除'}}
                            </span>
                        </template>
                    </el-table-column>
                    <template v-slot:append>
                        <div class="infinite-tips">
                            <p v-show="loading"><i class="el-icon-loading"></i></p>
                            <p v-show="fileSearch.noMore">没有更多啦</p>
                        </div>
                    </template>
                </el-table>
            </el-tab-pane>
        </el-tabs>
        <el-dialog top="30px" class="mk-file-preview" width="80%" title="文件预览" :visible.sync="preview.dialog" append-to-body center>
            <iframe class="mk-preview-iframe" :src="domain + preview.url" :style="{height: previewHeight}"></iframe>
        </el-dialog>
    </div>
    `,
    props: {
        value: {
            type: Array,
            default: [],
        },
        limit: {
            type: Number,
            default: -1,
        },
        fileType: {
            type: String,
            default: '',
        },
        height: {
            type: String,
            default: (window.innerHeight - 100) + 'px',
        },
    },
    data() {
        return {
            selectedList: this.value, //选择文件列表
            fileNowList: [],
            fileAllList: [],
            fileTypeList: [],
            fileSearch: {},
            fileTypeIndex: "0",
            fileTypeName: "",
            breadcrumb: [{'id': 0, 'title': '根目录'}],
            sortableList: [
                { title: "按修改时间排序", name: "create_time"},
                { title: "按文件大小排序", name: "size"},
                { title: "按文件名排序", name: "title"},
            ],
            acceptList: {
                image: '.png,.jpg,.jpeg,.bmp,.gif,.ico', 
                video: '.mp4', 
                audio: '.mp3', 
                word: '.docx,.doc', 
                other: '.swf,.psd,.css,.js,.html,.exe,.dll,.zip,.rar,.ppt,.pdf,.xlsx,.xls,.txt,.torrent,.dwt,.sql'
            },
            search: {
                pid: 0, 
                page: 1, 
                totalPage:1,
                isLoad: false,
                noMore:false,
                keyword: "",
            },
            sortable: {
                prop: "create_time", 
                order: "descending"
            },
            preview: {
                dialog: false,
                url: "",
            },
            pasteLoading: false,
            pasteType: "",
            pasteData: [],
            rows: [],
            loading: false,
            addFolderLoading: false,
            url: "file/index",
            addUrl: "file/upload",
            delUrl: "file/delete",
            editUrl: "file/update",
            recycleUrl: "file/recycle",
            addFolderUrl: "file/addFolder",
            pasteFolderUrl: "file/paste",
            countSizeUrl: "file/countSizeFolder",
            uploadType: "",
            UploadIndex: {},
        }
    },
    created() {
        this.getFileTypeList();
        this.getData();
    },
    computed:{
        previewHeight() {
            return (window.innerHeight - 310) + 'px';
        },
        addAuthority() {
            return authorityPath.indexOf(this.addUrl) !== -1;
        },
        delAuthority() {
            return authorityPath.indexOf(this.delUrl) !== -1;
        },
        editAuthority() {
            return authorityPath.indexOf(this.editUrl) !== -1;
        },
        recycleAuthority() {
            return authorityPath.indexOf(this.recycleUrl) !== -1;
        },
        addFolderAuthority() {
            return authorityPath.indexOf(this.addFolderUrl) !== -1;
        },
        pasteAuthority() {
            return authorityPath.indexOf(this.pasteFolderUrl) !== -1;
        },
        countSizeAuthority() {
            return authorityPath.indexOf(this.countSizeUrl) !== -1;
        },
        delOrRecycleAuthority() {
            return this.fileTypeName === 'recycle' ? this.delAuthority : this.recycleAuthority;
        },
    },
    methods: {
        /**
         * 当前类型
         */
        getFileTypeList() {
            let fileTypeList = [
                {name: "image", label: "图片", search: JSON.parse(JSON.stringify(this.search)), sortable: JSON.parse(JSON.stringify(this.sortable))},
                {name: "video", label: "视频", search: JSON.parse(JSON.stringify(this.search)), sortable: JSON.parse(JSON.stringify(this.sortable))},
                {name: "audio", label: "音乐", search: JSON.parse(JSON.stringify(this.search)), sortable: JSON.parse(JSON.stringify(this.sortable))},
                {name: "word",  label: "文档", search: JSON.parse(JSON.stringify(this.search)), sortable: JSON.parse(JSON.stringify(this.sortable))},
                {name: "other", label: "其它", search: JSON.parse(JSON.stringify(this.search)), sortable: JSON.parse(JSON.stringify(this.sortable))},
                {name: 'recycle', label: "回收站", search: JSON.parse(JSON.stringify(this.search)), sortable: JSON.parse(JSON.stringify(this.sortable))}
            ];
            switch(this.fileType) {
                case ('all'):
                    this.fileTypeList = fileTypeList;
                    break;
                case ('file'):
                    // 除了回收站以外
                    fileTypeList.splice(5, 1);
                    this.fileTypeList = fileTypeList;
                    break;
                default:
                    let index = common.arrayIndex(fileTypeList, this.fileType, 'name');
                    if (index !== -1) {
                        this.fileTypeList = [fileTypeList[index]]
                    } else {
                        console.log('请指定文件类型！');
                        return false;
                    }
            }
            // 默认值
            this.fileSearch   = this.fileTypeList[this.fileTypeIndex]['search'];
            this.fileTypeName = this.fileTypeList[this.fileTypeIndex]['name'];
        },
        /**
         * 获取数据
         */
        getData() {
            let self       = this;
            self.loading   = true;
            let fileSearch = JSON.parse(JSON.stringify(self.fileSearch));
            fileSearch['order']  = self.sortable['order'];
            fileSearch['prop']   = self.sortable['prop'];
            fileSearch['type']   = self.fileTypeName;
            fileSearch['status'] = fileSearch['type'] === 'recycle' ? 0 : 1;
            request.post(self.url, fileSearch, function(res) {
                res.data.forEach(function(item, index) {
                    if (common.arrayIndex(self.fileAllList, item.id) === -1) {
                        item = self.initData(item);
                        self.fileAllList.push(item);
                    }
                });
                self.fileSearch = Object.assign({}, self.fileSearch, {isLoad: true, totalPage: res.totalPage});
                self.loading    = false;
                self.listInit();
            });
        },
        /**
         * 初始化数据
         */
        initData(item) {
            let cover         = '/static/images/filecover/';
            let type          = file.getType(item.url);
            let size          = file.getSize(item.size);
            let urlArr        = item['url'].split('.');
            item['typeName']  = item.folder == 0 ? type.name : '文件夹';
            item['sizeName']  = item.folder == 0 ? size: '点击计算';
            item['cover']     = item.folder == 0 ? cover + type.type + '.png' : cover + 'folder.png';
            item['cover']     = type.type   === 'image' ? urlArr[0] + '40x40.' + urlArr[1]  : item['cover'];
            item['rename']    = true;
            item['shear']     = false;
            item['search']    = JSON.parse(JSON.stringify(this.search));
            item['countSizeLoading'] = false;
            return item;
        },
        /**
         * 排序
         */
        sortChange(v) {
            this.sortable = Object.assign({}, this.sortable, {prop: v.prop , order: v.order});
            this.searchInit();
        },
        /**
         * 刷新页面
         */ 
        refresh() {
            this.fileSearch = Object.assign({}, this.fileSearch, {keyword: ""});
            if (this.fileSearch.pid == 0) {
                this.breadcrumb = [{'id': 0, 'title': '根目录'}];
            }
            this.searchInit();
        },
        /**
         * 关键词搜索
         */
        searchKeyword() {
            if (this.fileSearch.keyword === "" && this.fileSearch.pid == 0) {
                this.breadcrumb = [{'id': 0, 'title': '根目录'}];
            }
            this.searchInit();
        },
        /**
         * 搜索初始化(关键词/排序名)
         */
        searchInit() {
            let self  = this;
            if (self.fileSearch.keyword !== "") {
                self.breadcrumb = [{'id': 0, 'title': '搜索结果'}];
            }
            self.fileSearch = Object.assign({}, self.fileSearch, {page: 1, noMore: false});
            // 当前列表清空
            self.fileNowList.forEach(function (item, key) {
                let index = self.fileAllList.indexOf(item);
                self.fileAllList.splice(index ,1);
            })
            self.fileNowList = [];
            // 重新加载
            self.getData();
        },
        /**
         * 文件夹选择
         * @param  {String} id 当前文件夹id
         */
        clickFolder(id) {
            if (id == 0) {
                let index       = this.fileTypeIndex;
                this.fileSearch = this.fileTypeList[index]['search'];
                this.fileSearch = Object.assign({}, this.fileSearch, {pid: id});
            } else {
                let index       = common.arrayIndex(this.fileAllList, id);
                this.fileSearch = this.fileAllList[index]['search'];
                this.fileSearch = Object.assign({}, this.fileSearch, {pid: id}); //noMore也可以放入
                if (this.fileSearch.isLoad === false) {
                    this.getData();
                }
            }
            this.listInit();
        },
        /**
         * 类型选择
         */
        changeFileType (tab) {
            let index    = tab['name'];
            let fileType      = this.fileTypeList[index];
            this.fileTypeName = fileType['name'];
            this.sortable     = fileType['sortable'];
            this.fileSearch   = fileType['search'];
            let title         = this.fileSearch.keyword === "" ? '根目录' : '搜索结果';
            this.breadcrumb   = [{'id': 0, 'title': title}];
            if (this.fileSearch.isLoad === false) {
                this.getData();
            }
            // 复制/粘贴初始化
            this.pasteInit();
            // 列表初始化
            this.listInit();
        },
        /**
         * 列表初始化
         */
        listInit() {
            let self    = this;
            let nowList = [];
            let search  = self.fileSearch;
            let type    = self.fileTypeName;
            self.fileAllList.forEach(function (item, index){
                // 回收站只需要状态相等
                if (type === 'recycle') {
                    if (item.status == 0) {
                        nowList.push(item);
                    }
                } else {
                    // 如果不是回收站则状态、类型必须一致
                    if (item.status === 1 && type === item.type) {
                        if (search.keyword === "") {
                            if (search.pid == item.pid) {
                                nowList.push(item);
                            }
                        } else {
                            if (item.title.indexOf(search.keyword) != -1) {
                                nowList.push(item);
                            }
                        }
                    }
                }
            });
            common.fileOrder(nowList);
            this.fileNowList = nowList;
        },
        /**
         * 分页改变时
         */
        pageChange() {
            if (this.loading === false) {
                if (this.fileSearch.noMore === false) {
                    if (this.fileSearch.totalPage > this.fileSearch.page) {
                        this.fileSearch.page++;
                        this.getData();
                    } else {
                        this.fileSearch  = Object.assign({}, this.fileSearch, {noMore: true});
                    }
                }
            }
        },
        /**
         * 后退
         */
        back() {
            if (this.fileSearch.keyword === '') {
                let crumb = this.breadcrumb;
                let index = crumb.length - 1;
                crumb.splice(index, 1);
                this.clickFolder(crumb[crumb.length - 1]['id']);
            } else {
                this.fileSearch.keyword = '';
                this.searchKeyword();
            }
        },
        /**
         * 面包屑
         * @param  {String} val 当前父级
         */
        clickBreadcrumb(index) {
            let crumb = this.breadcrumb;
            crumb.splice(index+1,crumb.length);
            this.clickFolder(crumb[crumb.length - 1]['id']);
        },
        /**
         * 查看
         * @param  {Object} row 单行
         */
        see(row, index) {
            if (row.rename === true) {
                if (row.folder === 1) {
                    if (row.status === 1){
                        let crumb = this.breadcrumb;
                        crumb.push({'id': row.id, 'title': row.title});
                        this.clickFolder(row.id);
                    }
                } else {
                    let type = file.getType(row.url);
                    if (type.type === 'image') {
                        this.$refs['preview' + index][0].clickHandler();
                    } else {
                        this.preview.url    = row.url;
                        this.preview.dialog = true;
                    }
                }
            }
        },
        /**
         * 预览列表
         */
        srcList(index) {
            if (this.fileTypeName === 'image') {
                let arr = [];
                this.fileNowList.forEach(function (item, index) {
                    if (item.folder === 0) arr.push(domain + item.url);
                });
                return arr;
            } else {
                return [domain + this.fileNowList[index]['url']];
            }
        },
        /**
         * 行不可选中
         * @param  {Object} row   当前行
         */
        checkDisabled(row) {
            if (this.fileType !== 'all') {
                return row.folder === 1 ? false : true;
            } else {
                return true;
            }
        },
        /**
         * 计算文件夹大小
         * @param  {Object} row   当前行
         */
        countSize(row) {
            let self = this;
            row.countSizeLoading = true;
            request.post(self.countSizeUrl, {'id': row.id}, function(res) {
                row.countSizeLoading = false;
                if(res.status === 'success') {
                    row.sizeName = file.getSize(res.data);;
                } else {
                    self.$message({ showClose: true, message: res.message, type: res.status});
                }
            });
        },
        /**
         * 选中行状态改变
         * @param  {Object} rows 多行
         */
        checkSelected(rows) {
            this.rows = rows;
        },
        /**
         * 点击行选中
         */
        clickSelected(row) {
            if (this.fileType === 'all' || row.folder === 0) {
                let refName  = "table" + this.fileTypeIndex;
                this.$refs[refName][0].toggleRowSelection(row);
                this.selectedFile(this.rows, row);
            }
        },
        /**
         * 选择文件（需要与侧边栏匹配）
         * @return {rows} 多行
         * @return {row}  当前行
         */
        selectedFile(rows, row) {
            if (this.fileType !== 'all') {
                let selected = rows.length && rows.indexOf(row) !== -1;
                let refName  = "table" + this.fileTypeIndex;
                if (selected) {
                    // 选择文件超出限制
                    if (this.limit !== 0 && this.selectedList.length >= this.limit) {
                        let index = this.selectedList.length - 1;
                        this.selectedList.splice(index, 1);
                    }
                    this.selectedList.push(row);
                } else {
                    let index = common.arrayIndex(this.selectedList, row.id);
                    this.selectedList.splice(index, 1);
                }
            }
        },
        /**
         * 粘贴状态初始化
         */
        pasteInit() {
            this.pasteType = "";
            this.pasteData = [];
            this.fileAllList.forEach(function (item, index) {
                item['shear'] = false;
            });
        },
        /**
         * 剪切
         * @param  {Object} row 单行
         */
        shear(row = "") {
            this.pasteInit();
            this.pasteType = "shear";
            this.pasteData = row === "" ? this.rows : [row];
            this.pasteData.forEach(function (item, index) {
                item['shear'] = true;
            });
        },
        /**
         * 粘贴
         */
        paste() {
            let self = this;
            // 剪切时
            let crumb = this.breadcrumb;
            let idArr = common.arrayColumn(crumb, 'id');
            let isSub = -1;
            self.pasteData.forEach(function (pasteItem, pasteIndex) {
                // 判断目标文件夹是源文件的子文件夹
                if (idArr.indexOf(pasteItem.id) !== -1) {
                    isSub = pasteIndex;
                }
                // 删除已被剪切的数据
                let index = self.fileAllList.indexOf(pasteItem);
                if (index !== -1) {
                    self.fileAllList.splice(index, 1);
                }
            });
            if (isSub !== -1){
                self.pasteData.splice(isSub, 1);
                self.$message({ showClose: true, message: '目标文件夹是源文件的子文件夹', type: 'warning'}); 
            }
            if (self.pasteData.length > 0) {
                self.pasteLoading = true;
                request.post(self.pasteFolderUrl, {'pid': self.fileSearch.pid, 'data': self.pasteData}, function(res) {
                    if(res.status === 'success') {
                        res.data.forEach(function (item, index) {
                            item = self.initData(item);
                        });
                        self.fileAllList = res.data.concat(self.fileAllList);
                        self.listInit();
                    } else {
                        self.$message({ showClose: true, message: res.message, type: res.status});
                    }
                    self.pasteLoading = false;
                });
                self.pasteInit();
            }
        },
        /**
         * 清空回收站
         */
        clear() {
            let self       = this;
            self.$confirm('确定清空回收站吗？', '', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                request.post(self.delUrl, {}, function(res){
                    if(res.status === 'success') {
                        self.refresh();
                        self.listInit();
                        self.pasteInit();
                    } else {
                        self.$message({ showClose: true, message: res.message, type: res.status});
                    }
                });
            }).catch(() => {});
        },
        /**
         * 删除文件、批量删除
         * @param  {Object} row  当前行
         */
        del(row = "") {
            let self       = this;
            let type       = self.fileTypeName;
            let tips       = type === "recycle" ? '确定永久删除文件吗？' : '确定放入回收站吗？';
            let requestUrl = type === "recycle" ? self.delUrl : self.recycleUrl;
            let delList    = row === "" ? self.rows : [row];
            let delIds     = common.arrayColumn(delList,'id');
            self.$confirm(tips, '', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                request.post(requestUrl, {ids: delIds, status: 0}, function(res){
                    if(res.status === 'success') {
                        delList.forEach(function (item, key) {
                            let index = self.fileAllList.indexOf(item);
                            if (index !== -1) {
                                // 永久删除/放入回收站
                                if (type === "recycle") {
                                    self.fileAllList.splice(index, 1);
                                } else {
                                    self.fileAllList[index]['status'] = 0;
                                }
                            }
                            // 移除已选中的项
                            let sindex = self.selectedList.indexOf(item);
                            self.selectedList.splice(sindex, 1);
                        });
                        self.listInit();
                        self.pasteInit();
                    } else {
                        self.$message({ showClose: true, message: res.message, type: res.status});
                    }
                });
            }).catch(() => {});
        },
        /**
         * 还原文件、批量还原
         * @param  {Object} row  当前行
         */
        reduction(row = "") {
            let self = this;
            let list = row === "" ? self.rows : [row];
            let ids  = common.arrayColumn(list, 'id');
            request.post(self.recycleUrl, {ids: ids, status: 1}, function(res){
                if(res.status === 'success') {
                    list.forEach(function (item, key) {
                        let index = self.fileAllList.indexOf(item);
                        if (index !== -1) {
                            self.fileAllList[index]['status'] = 1;
                        }
                    });
                    self.listInit();
                } else {
                    self.$message({ showClose: true, message: res.message, type: res.status});
                }
            });
        },
        /**
         * 新建文件夹
         * @param  {Object} rows 多行数
         */
        addFolder() {
            let self  = this;
            let type  = self.fileTypeName;
            self.addFolderLoading = true;
            request.post(self.addFolderUrl, {'pid': self.fileSearch.pid, 'type': type}, function(res) {
                self.addFolderLoading = false;
                if (res.status === 'success') {
                    self.fileAllList.unshift(self.initData(res.data));
                    self.listInit();
                } else {
                    self.$message({ showClose: true, message: res.message, type: "error"});
                }
            });
        },
        /**
         * 单字段修改
         * @param  {Object} row 当前行
         */
        fieldEdit(row, field) {
            let self = this;
            request.post(self.editUrl, {id: row.id, value: row[field], field: field}, function(res) {
                if (res.status != "success") {
                    self.getData();
                } else {
                    self.$message({ showClose: true, message: res.message, type: res.status});
                }
            });
        },
        /**
         * 重命名修改
         * @param  {Object} row 当前行
         */
        changeRename(row) {
            this.fieldEdit(row, 'title');
        },
        /**
         * 点击重命名
         * @param  {Object} row 当前行
         */
        clickRename(row) {
            let self = this;
            self.blurRename();
            row.rename = false;
            self.$nextTick(()=>{
                self.$refs[`title${row.id}`].forEach(function (item, index) {
                    self.$refs[`title${row.id}`][index].focus();
                    self.$refs[`title${row.id}`][index].select();
                })
            });
        },
        /**
         * 重命名失去焦点
         * @param  {Object} row 当前行
         */
        blurRename() {
            this.fileAllList.forEach(function(item, index) {
                item.rename = true;
            })
        },
        /**
         * 上传文件开启
         * @param  {Object} item  当前文件
         */
        beforeUpload(item) {
            // 文件夹最尾下标
            let index     = -1;
            this.fileNowList.forEach(function (folderItem, folderIndex) {
                index = folderItem['folder'] === 1 && folderIndex > index ? folderIndex : index;
            });
            let fileItem = {};
            fileItem['uid']         = item.uid;
            fileItem['percentage']  = 0;
            fileItem['title']       = item.name;
            fileItem['type']        = file.getType(item.name)['type'];
            fileItem['folder']      = 0;
            fileItem['create_time'] = common.dateTime();
            fileItem['status']      = 1;
            fileItem['rename']      = true;
            fileItem['typeName']    = file.getType(item.name)['name'];
            fileItem['size']        = file.getSize(item.size);
            this.fileNowList.splice(index+1, 0, fileItem);
        },
        /**
         * 上传文件中
         * @param  {Object} event
         * @param  {Object} item  当前文件
         */
        progressUpload(event, item) {
            let index    = common.arrayIndex(this.fileNowList, item['uid'], 'uid');
            this.fileNowList[index]['percentage'] = Math.round(item.percentage);
        },
        /**
         * 上传成功回调
         * @param  {Object} res   返回当前状态
         * @param  {Object} item  当前文件
         */
        successUpload(res, item) {
            var self     = this;
            var index    = common.arrayIndex(self.fileNowList, item['uid'], 'uid');
            if (res.status === 'success') {
                self.fileNowList[index]['percentage'] = 100;
                var time;
                time = setTimeout(function () {
                    let data = self.initData(res.data);
                    self.fileNowList.splice(index, 1, data);
                    self.fileAllList.unshift(data);
                }, 1200);
            } else {
                self.fileNowList.splice(self.UploadIndex,1);
                self.$message({showClose: true, message: res.message, type: 'error'});
            }
        },
        /**
         * 上传错误回调
         * @param  {Object} err 错误信息
         */
        errorUpload(err) {
            this.fileNowList.splice(this.UploadIndex,1);
        },
    },
    watch: {
        /**
         * 给类型排序赋值
         */
        sortable(v) {
            this.fileTypeList[this.fileTypeIndex]['sortable'] = v; 
        },
        /**
         * 搜索条件赋值(文件夹/类型)
         */
        fileSearch(v) {
            if (v.pid !== 0) {
                let index = common.arrayIndex(this.fileAllList, v.pid);
                this.fileAllList[index]['search'] = v;
            } else {
                let index = this.fileTypeIndex;
                this.fileTypeList[index]['search'] = v;
            }
        },
        /**
         * 选择文件（需要与侧边栏匹配）
         */
        selectedList(v) {
            let self     = this;
            let refName  = "table" + this.fileTypeIndex;
            this.fileAllList.forEach(function (row, index) {
                if (v.indexOf(row) === -1) {
                    self.$refs[refName][0].toggleRowSelection(row, false);
                }
            });
            this.$emit('input', v);
        },
        value(v) {
            this.selectedList = v;
        },
    }
});
/**
 * 文件预览
 */
Vue.component('mk-file-preview', {
    template: `
    <el-dialog
        top="30px"
        class="mk-file-preview"
        width="80%"
        :title="preview.title"
        :visible.sync="preview.dialog"
        append-to-body
        center>
        <div 
            v-if="preview.type === 'image'"  
            style="overflow: auto;"
            :style="{maxHeight: window.innerHeight - 270 + 'px'}">
            <el-image :src="domain + preview.url">
                <div slot="error" class="image-slot">
                    <img class="error-image" :src="static + '/images/error.png'"/>
                </div>
            </el-image>
        </div>
        <iframe 
            v-else 
            class="mk-preview-iframe" 
            :src="domain + preview.url"
            :style="{height: previewHeight}">
        </iframe>
    </el-dialog>
    `,
    props: {
        preview: {
            type: Object,
            default: {},
        },
    },
    data() {
        return {
            ctitle:"",
        }
    },
    computed:{
        previewHeight() {
            return (window.innerHeight - 310) + 'px';
        },
        imageHeight() {
            return (window.innerHeight - 200) + 'px';
        }
    },
});
/**
 * 单文件选择
 */
Vue.component('mk-file-select', {
    template: `
    <div class="mk-file-select">
        <div class="mk-file-cover" :style="{width: width + 'px', height: height + 'px'}">
            <el-image ref="preview" :preview-src-list="[domain + cover]" :src="domain + cover">
                <div slot="error" class="image-slot">
                    <img class="error-image" :src="static + '/images/error.png'"/>
                </div>
            </el-image>
            <i class="el-icon-close" @click="file = ''"></i>
            <div class="mk-file-tips">
                <div class="icon">
                    <i class="el-icon-folder-opened" v-if="! disabled" title="从资源库中选择" @click="dialog = true"></i>
                    <i class="el-icon-search" title="查看大图" @click="clickPreview()"></i>
                </div>
            </div>
        </div>
        <mk-file-dialog v-model="dialog" :title="dialogTitle" :list="[]" :type="type" :limit="1" @success-selected="fileSuccess($event)"></mk-file-dialog>
        <el-dialog top="30px" class="mk-file-preview" width="80%" title="文件预览" :visible.sync="preview" append-to-body center>
            <iframe class="mk-preview-iframe" :src="domain + file" :style="{height: previewHeight}"></iframe>
        </el-dialog>
    </div>`,
    props: {
        dialogTitle: {
            type: String,
            default: '文件选择',
        },
        tips: {
            type: String,
            default: '选择文件',
        },
        value: {
            type: String,
            default: ''
        },
        type: {
            type: String,
            default: 'image'
        },
        width: {
            type: Number,
            default: 56
        },
        height: {
            type: Number,
            default: 56
        },
        disabled: {
            type: Boolean,
            default: false,
        }
    },
    data() {
        return {
            file: this.value,
            cover: "",
            dialog: false,
            preview: false
        }
    },
    created() {
        this.getFileCover();
    },
    computed: {
        previewHeight() {
            return (window.innerHeight - 310) + 'px';
        },
        fileType() {
            let type = file.getType(this.file);
            return type.type;
        },
    },
    methods: {
        /**
         * 获取封面图
         */
        getFileCover() {
            if (this.file != "") {
                this.cover = this.fileType === 'image' ? this.file : '/static/images/filecover/' + this.fileType + '.png';
            } else {
                this.cover = "";
            }
        },
        /**
         * 文件预览
         */
        clickPreview() {
            if (this.file != "") {
                if (this.fileType === 'image') {
                    this.$refs.preview.clickHandler();
                } else {
                    this.preview = true;
                }
            }
        },
        /**
         * 文件选择成功
         */
        fileSuccess(list) {
            this.cover = list[0]['cover'];
            this.file  = list[0]['url'];
        },
    },
    watch: {
        value(v) {
            this.file = v;
            this.getFileCover();
        },
        file(v) {
            this.$emit('input', v);
        }
    }
});
/**
 * 多文件选择
 */
Vue.component('mk-file-list-select', {
    template: `
    <div class="mk-file-list-select">
        <div 
            class="mk-select-item mk-upload" 
            @click="openDialog()" 
            :style="{width: width + 'px', height: width + 'px',background: disabled ? '#eee' : '#fff', cursor: disabled ? 'not-allowed' : 'pointer'}">
            <i class="el-icon-plus"></i>
        </div>
        <div v-if="list.length === 0" style="display: inline-block;height: 58px;line-height: 58px;color: #999">未选择</div>
        <draggable class="mk-select-list" v-model="list" v-bind="draggable">
            <div class="mk-select-item mk-select-item-cover" v-for="(item, index) in previewList" :key="index">
                <div class="mk-file-cover" :style="{width: width + 'px', height: width + 'px'}">
                    <el-image :src="domain + item.cover" :ref="'preview' + index" :preview-src-list="srcList(index)">
                        <div slot="error" class="image-slot">
                            <img class="error-image" :src="static + '/images/error.png'"/>
                        </div>
                    </el-image>
                    <i class="el-icon-close" @click="list.splice(index, 1)"></i>
                    <div class="mk-file-tips">
                        <div class="icon">
                            <i class="el-icon-folder-opened" v-if="! disabled" title="从资源库中选择" @click="dialog = true"></i>
                            <i class="el-icon-search" title="查看大图" @click="clickPreview(item, index)"></i>
                        </div>
                    </div>
                </div>
            </div>
        </draggable>
        <mk-file-dialog v-model="dialog" :list="list" :type="type" :limit="0" @success-selected="fileSuccess($event)"></mk-file-dialog>
        <el-dialog top="30px" class="mk-file-preview" width="80%" title="文件预览" :visible.sync="preview.dialog" append-to-body center>
            <iframe class="mk-preview-iframe" :src="domain + preview.url" :style="{height: previewHeight}"></iframe>
        </el-dialog>
    </div>
    `,
    props: {
        value: {
            type: Array,
            default: [],
        },
        type: {
            type: String,
            default: 'image'
        },
        width: {
            type: Number,
            default: 56
        },
        link: {
            type: Boolean,
            default: false,
        },
        disabled: {
            type: Boolean,
            default: false,
        }
    },
    data() {
        return {
            list: this.value,
            dialog: false,
            preview: {
                dialog: false,
                url: "",
            },
            draggable: {
                handle: '.mk-select-item-cover',
                animation: 300,
                forceFallback: true,
            }
        }
    },
    computed: {
        previewHeight() {
            return (window.innerHeight - 310) + 'px';
        },
        previewList() {
            let arr = this.list;
            arr.forEach(function (item, index) {
                let type   = file.getType(item.url);
                item.cover = type.type === 'image' ? item.url : '/static/images/filecover/' + type.type + '.png';
            });
            return arr;
        },
    },
    methods: {
        /**
         * 预览列表
         */
        srcList(index) {
            if (this.type === 'image') {
                let arr = [];
                this.list.forEach(function (item, index) {
                    arr.push(domain + item.url);
                });
                return arr;
            } else {
                return [domain + this.list[index]['url']];
            }
        },
        /**
         * 文件预览
         */
        clickPreview(item, index) {
            let type = file.getType(item.url);
            if (type.type === 'image') {
                this.$refs['preview' + index][0].clickHandler();
            } else {
                this.preview.url    = item.url;
                this.preview.dialog = true;
            }
        },
        /**
         * 打开列表
         */
        openDialog() {
            if (! this.disabled) {
                this.dialog = true;
            }
        },
        /**
         * 文件选择成功
         */
        fileSuccess(list) {
            if (this.link === true) {
                list.forEach(function (item, index) {
                    item.link = "";
                });
            }
            this.list = list;
        },
    },
    watch: {
        value(v) {
            this.list = v;
        },
        list(v) {
            this.$emit('input', v);
        },
    }
});
/**
 * 文件弹窗选择
 */
Vue.component('mk-file-dialog', {
    template: `
    <el-dialog
        top="30px"
        v-if="fileDialog"
        class="mk-file-dialog"
        :title="title"
        width="980px"
        :modal="false"
        :visible.sync="fileDialog"
        :close-on-click-modal="false"
        :before-close="close">
        <mk-file-list
            :file-type="type" 
            :limit="limit"
            :height="(window.innerHeight - 314) + 'px'"
            v-model="selectedList">
        </mk-file-list>
        <div class="mk-file-selected">
            <div class="mk-limit-tips">
                <template v-if="limit === 0">无限制选择</template>
                <template v-else>选择限制<span>{{selectedList.length}}/{{limit}}</span></template>
                <div v-if="selectedList.length === 0" style="margin-top:10px;color: #999">未选择</div>
            </div>
            <div class="mk-list-selected">
                <div 
                    class="mk-item-selected" 
                    v-for="(item, index) in previewList" 
                    :key="index">
                    <el-image :src="domain + item.cover" :ref="'preview' + index" :preview-src-list="srcList(index)">
                        <div slot="error" class="image-slot">
                            <img class="error-image" :src="static + '/images/error.png'"/>
                        </div>
                    </el-image>
                    <div class="mk-file-tips">
                        <div class="icon">
                            <i class="el-icon-search" title="查看大图" @click="clickPreview(item, index)"></i>
                        </div>
                    </div>
                    <i class="el-icon-close" @click.stop="removeFile(index)"></i>
                </div>
            </div>
        </div>
        <el-dialog top="30px" class="mk-file-preview" width="80%" title="文件预览" :visible.sync="preview.dialog" append-to-body center>
            <iframe class="mk-preview-iframe" :src="domain + preview.url" :style="{height: previewHeight}"></iframe>
        </el-dialog>
        <span slot="footer" class="dialog-footer">
            <el-button @click="close()" size="small">取 消</el-button>
            <el-button type="primary" @click="selected" size="small">确 定</el-button>
        </span>
    </el-dialog>`,
    props: {
        title: {
            type: String,
            default: '文件选择',
        },
        list: {
            type: Array,
            default: [],
        },
        type: {
            type: String,
            default: 'image', //image video audio word other file
        },
        limit:{
            type: Number,
            default: 1, 
        },
        value: {
            type: Boolean,
            default: false,
        },
    },
    data() {
        return {
            fileDialog: this.value,
            selectedList: JSON.parse(JSON.stringify(this.list)),
            preview: {
                dialog: false,
                url: "",
            },
        }
    },
    computed: {
        previewHeight() {
            return (window.innerHeight - 310) + 'px';
        },
        previewList() {
            let arr = this.selectedList;
            arr.forEach(function (item, index) {
                let type   = file.getType(item.url);
                item.cover = type.type === 'image' ? item.url : '/static/images/filecover/' + type.type + '.png';
            });
            return arr;
        },
    },
    methods: {
        /**
         * 预览列表
         */
        srcList(index) {
            if (this.type === 'image') {
                let arr = [];
                this.selectedList.forEach(function (item, index) {
                    arr.push(domain + item.url);
                });
                return arr;
            } else {
                return [domain + this.selectedList[index]['url']];
            }
        },
        /**
         * 文件预览
         */
        clickPreview(item, index) {
            let type = file.getType(item.url);
            if (type.type === 'image') {
                this.$refs['preview' + index][0].clickHandler();
            } else {
                this.preview.url    = item.url;
                this.preview.dialog = true;
            }
        },
        /**
         * 删除文件
         * @param  {Number} index 下标
         */
        removeFile(index) {
            this.selectedList.splice(index, 1);
        },
        /**
         * 选择完毕
         */
        selected() {
            this.fileDialog = false;
            this.$emit('success-selected',this.selectedList);
        },
        /**
         * 关闭弹窗
         */
        close() {
            this.fileDialog = false;
        }
    },
    watch: {
        value(v) {
            this.fileDialog = v;
        },
        list(v) {
            this.selectedList = JSON.parse(JSON.stringify(v));
        },
        fileDialog(v) {
            this.$emit('input', v);
        },
    }
});
/**
 * 设置链接
 */
Vue.component('mk-link', {
    template:`
    <div class="mk-link">
        <el-input 
            v-if="linkForm" 
            v-model="linkForm.title" 
            style="width: 200px" 
            :size="size" 
            :disabled="true">
        </el-input>
        <el-button 
            @click="linkFormDialog = true" 
            :size="size" 
            plain>
            设置链接
        </el-button>
        <el-dialog
            top="30px"
            v-if="linkFormDialog"
            title="设置链接"
            width="600px"
            :visible.sync="linkFormDialog"
            :close-on-click-modal="false"
            append-to-body>
            <el-form :model="linkForm" label-width="150px">
                <el-form-item label="链接类型：" prop="type">
                    <el-radio-group v-model="linkForm.type">
                        <el-radio 
                            v-for="(item, index) in typeList" 
                            :label="String(index)" 
                            :key="index"  
                            @change="typeChange()">
                            {{item}}
                        </el-radio>
                    </el-radio-group>
                </el-form-item>
            </el-form>
            <el-form :model="valueForm" ref="valueForm" :rules="rulesValueForm" label-width="150px" :validate-on-rule-change="false">
                <template v-if="linkForm.type == 1">
                    <el-form-item label="自定义地址：" prop="value">
                        <el-input v-model="valueForm.value" placeholder="请输入链接必须带有http://或https://" style="width: 300px"></el-input>
                    </el-form-item>
                </template>
                <template v-else-if="linkForm.type == 2">
                    <el-form-item label="详情链接：" prop="linkName">
                        <el-select 
                            style="width: 300px"
                            v-model="valueForm.linkName"
                            @change="linkChange()"
                            filterable>
                            <el-option 
                                v-for="(item, index) in linkList" 
                                :label="item.title"
                                :value="item.name">
                            </el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item :label="linkTile + '：'" prop="value">
                        <el-select
                            :placeholder="'输入' + linkTile + '标题可远程搜索'"
                            :loading="paraLoading"
                            style="width: 300px"
                            v-model="valueForm.value"
                            @change="valueChange()" 
                            reserve-keyword
                            filterable
                            remote
                            :remote-method="getParaList">
                            <el-option 
                                v-for="(item, index) in paraList"
                                :key="index"
                                :label="item.title"
                                :value="String(item.id)">
                                <span v-if="typeof item.treeString != 'undefined'" v-html="item.treeString" class="mk-tree-name"></span>
                                {{ item.title }}
                            </el-option>
                        </el-select>
                    </el-form-item>
                </template>
                <template v-else-if="linkForm.type == 3">
                    <el-form-item label="分类链接：" prop="pageId">
                        <el-select 
                            :loading="pageLoading"
                            style="width: 300px"
                            v-model="valueForm.pageId"
                            filterable>
                            <el-option 
                                v-for="(item, index) in pageList" 
                                :key="index"
                                :label="item.title"
                                :value="String(item.id)">
                                <span v-html="item.treeString" class="mk-tree-name"></span>
                                {{ item.title }}
                            </el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="锚点名称：" prop="value">
                        <el-input style="width: 300px" v-model="valueForm.value" placeholder="如：#about"></el-input>
                    </el-form-item>
                </template>
                <el-form-item prop="targer" v-if="linkForm.type != 0">
                    <el-checkbox v-model="linkForm.targer" true-label="1" false-label="0">在新页面打开</el-checkbox>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" @click="determine" size="small">确定</el-button>
                    <el-button @click="linkFormDialog = false" size="small">取消</el-button>
                </el-form-item>
            </el-form>
        </el-dialog>
    </div>`,
    props: {
        value: {
            type: Object,
            default: {},
        },
        size: {
            type: String,
            default: '',
        },
    },
    data() {
        return {
            url: "config/link",
            catalogUrl: "catalog/index",
            pageList: [],
            paraList: [],
            pageLoading: false,
            paraLoading: false,
            typeList: ['无', '站外链接', '详情链接', '分类链接'],
            linkList: [],
            linkForm: this.value,
            linkTile: "",
            valueForm: {},
            indexForm: "",
            linkFormDialog: false,
        }
    },
    computed: {
        rulesValueForm() {
            let rules = {};
            switch(this.indexForm){
                case ("0"):
                    rules = {};
                    break;
                case ("1"):
                    rules = {
                        value: [
                            { required: true, message: '请输入', trigger: 'blur' },
                            { pattern: /(http|https):\/\/([\w.]+\/?)\S*/, message: '必须带有http://或https://', trigger: 'blur' },
                        ],
                    }
                    break;
                case ("2"):
                    rules = {
                        linkName: [
                            { required: true, message: '请选择', trigger: 'blur' },
                        ],
                        value: [
                            { required: true, message: '请选择', trigger: 'blur' },
                        ],
                    }
                    break;
                case ("3"):
                    rules = {
                        pageId: [
                            { required: true, message: '请选择', trigger: 'blur' },
                        ],
                    }
                    break;
            }
            return rules;
        },
    },
    methods: {
        /**
         * 初始化
         */
        init() {
            this.getLinkList();
        },
        /**
         * 获取数据
         */
        getLinkList() {
            let self = this;
            if (self.linkForm === "" || self.linkForm === null || self.linkForm === "null" || JSON.stringify(self.linkForm) == "{}"  || typeof self.linkForm === "undefined") {
                self.linkForm = {
                    type: "0",
                    title: "",
                    targer: "0",
                    value: [
                        {value: ""},
                        {value: ""},
                        {value: "", linkName: ""},
                        {value: "", pageId: ""},
                    ],
                }
            }
            self.indexForm = self.linkForm.type;
            self.valueForm = self.linkForm['value'][self.indexForm];
            request.post(self.url, {}, function(res) {
                self.linkList = res.data;
                if (self.linkList.length > 0 && self.linkForm.value[2]['linkName'] === "") {
                    self.linkForm.value[2]['linkName'] = self.linkList[0]['name'];
                }
                self.getParaList();
                self.getPageList();
            });
        },
        /**
         * 获取站内列表
         */
        getParaList(keyword = "") {
            if (this.indexForm === '2') {
                let self      = this;
                let index     = self.valueForm.linkName === "" ? 0 : common.arrayIndex(self.linkList, self.valueForm.linkName, "name");
                let search    = self.linkList[index];
                self.linkTile = search['title'];
                self.paraLoading = true;
                request.post(self.url, {search: search['search'], table: search['table'], keyword: keyword}, function(res) {
                    self.paraLoading = false;
                    self.paraList = self.linkList[index]['table'] === 'catalog' ? tree.convertString(res.data) :res.data;
                });
            }
        },
        /**
         * 获取栏目列表
         */
        getPageList() {
            if (this.indexForm === '3') {
                let self  = this;
                let index = common.arrayIndex(self.linkList, self.valueForm.linkName, "name");
                self.pageLoading = true;
                request.post(self.catalogUrl, {}, function(res) {
                    let pageList = [];
                    res.data.forEach(function(item, index) {
                        if (item.links_type == 0)  pageList.push(item);
                    })
                    self.pageList    = tree.convertString(pageList);
                    self.pageLoading = false;
                });
            }
        },
        /**
         * 类型改变
         */
        typeChange() {
            this.indexForm = this.linkForm.type;
            this.valueForm = this.linkForm['value'][this.indexForm];
            this.getParaList();
            this.getPageList();
            this.$refs.valueForm.clearValidate();
        },
        /**
         * 链接改变
         */
        linkChange() {
            this.getParaList();
            let index = common.arrayIndex(this.linkList, this.valueForm.linkName, "name");
            this.valueForm.value = this.linkList[index]['value'];
        },
        /**
         * 值改变
         */
        valueChange() {
            let index = common.arrayIndex(this.linkList, this.valueForm.linkName, "name");
            this.linkList[index]['value'] = this.valueForm.value;
        },
        /**
         * 确定
         */
        determine() {
            this.$refs.valueForm.validate((valid) => {
                if (valid) {
                    if (this.indexForm === '2') {
                        let index = common.arrayIndex(this.paraList, this.valueForm.value, "id");
                        this.linkForm.title = this.paraList[index]['title'];
                    } else {
                        this.linkForm.title = this.valueForm.value;
                    }
                    this.linkFormDialog = false;
                    this.$emit("input", this.linkForm);
                } else {
                    return false;
                }
            });
        },
    },
    watch: {
        value(v) {
            this.linkForm = v;
        },
        linkFormDialog(v) {
            if (v === true) {
                this.init();
            }
        },
    }
}) 
/**
 * 自定义字段组件
 */
Vue.component('mk-field', {
    template:`
    <div class="mk-field">
        <el-form :model="ruleForm" :rules="rules" ref="ruleForm" :label-width="labelWidth" v-if="ifset">
            <el-form-item label="字段标题：" prop="label"> 
                <el-input v-model="ruleForm.label" placeholder="如：关于我们"></el-input>
            </el-form-item>
            <el-form-item label="字段变量：" prop="field">
                <el-input v-model="ruleForm.field" placeholder="如：about_us"></el-input>
            </el-form-item>
            <el-form-item label="字段类型：" prop="name">
                <el-select 
                    placeholder="请选择字段类型"
                    v-model="ruleForm.name" 
                    @change="fieldTypeChange(ruleForm)"
                    filterable>
                    <el-option
                        v-for="(item, index) in common.formType()"
                        :key="index"
                        :label="item.title"
                        :value="item.name">
                    </el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="字段值：" prop="value">
                <component
                    v-model="ruleForm.value"
                    :is="ruleForm.bind"
                    :key="ruleForm.name"
                    :type="ruleForm.type"
                    :format="ruleForm.format"
                    :value-format="ruleForm.valueFormat"
                    :options="region"
                    :predefine="predefineColors"
                    active-color="#13ce66"
                    show-alpha>
                </component>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" size="small" @click="addItem()">添加自定义字段</el-button>
            </el-form-item>
        </el-form>
        <el-empty v-if="ifset && list.length === 0" description="暂无自定义字段"></el-empty>
        <el-form :label-width="labelWidth">
            <el-form-item v-if="ifset">
                <el-input 
                    v-model="keyword" 
                    placeholder="输入字段标题或字段变量关键词搜索..." 
                    prefix-icon="el-icon-search">
                </el-input>
            </el-form-item>
            <draggable
                v-model="list" 
                v-bind="draggable">
                <template v-for="(item, index) in list" :key="index">
                    <template v-if="typeof item.label !== 'undefined' && item.label != ''">
                        <el-form-item v-show="item.label.indexOf(keyword) != -1 || item.field.indexOf(keyword) != -1">
                            <template slot="label">
                                <el-tooltip placement="top" :content="item.field">
                                    <div>{{item.label}}：</div>
                                </el-tooltip>
                            </template>
                            <component
                                class="mk-field-item-value"
                                v-model="item.value"
                                :is="item.bind"
                                :key="item.name"
                                :type="item.type"
                                :format="item.format"
                                :value-format="item.valueFormat"
                                :options="region"
                                :predefine="predefineColors"
                                active-color="#13ce66"
                                show-alpha>
                            </component>
                            <div class="mk-field-button" v-if="ifset">
                                <el-tooltip content="拖放排序" placement="top" >
                                    <el-button size="mini" class="rank" type="info" icon="el-icon-rank" circle></el-button>
                                </el-tooltip>
                                <el-tooltip content="设置" placement="top">
                                    <el-button size="mini" type="primary" icon="el-icon-s-tools" circle @click="setItem(item, index)"></el-button>
                                </el-tooltip>
                                <el-tooltip content="删除" placement="top">
                                    <el-button size="mini" type="danger" icon="el-icon-close" circle @click="list.splice(index, 1)"></el-button>
                                </el-tooltip>
                            </div>
                        </el-form-item>
                    </template>
                </template>
            </draggable>
        </el-form>
        <el-dialog
            :visible.sync="setShow"
            title="字段设置"
            width="600px"
            top="30px"
            append-to-body>
            <el-form 
                :model="setForm" 
                :rules="rules" 
                ref="setForm" 
                :label-width="labelWidth"
                :style="{height: window.innerHeight - 270 + 'px'}" 
                style="overflow: auto;">
                <el-form-item label="字段标题：" prop="label"> 
                    <el-input v-model="setForm.label" placeholder="如：关于我们"></el-input>
                </el-form-item>
                <el-form-item label="字段变量：" prop="field">
                    <el-input v-model="setForm.field" placeholder="如：about_us"></el-input>
                </el-form-item>
                <el-form-item label="字段类型：" prop="name">
                    <el-select 
                        placeholder="请选择字段类型"
                        v-model="setForm.name" 
                        @change="fieldTypeChange(setForm)"
                        filterable>
                        <el-option
                            v-for="(item, index) in common.formType()"
                            :key="index"
                            :label="item.title"
                            :value="item.name">
                        </el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="字段值：" prop="value">
                    <component
                        v-model="setForm.value"
                        :is="setForm.bind"
                        :key="setForm.name"
                        :type="setForm.type"
                        :format="setForm.format"
                        :value-format="setForm.valueFormat"
                        :options="region"
                        :predefine="predefineColors"
                        active-color="#13ce66"
                        show-alpha>
                    </component>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" size="small" @click="addItem()">添加自定义字段</el-button>
                </el-form-item>
            </el-form>
            <span slot="footer" class="dialog-footer">
                <el-button @click="setShow = false">取 消</el-button>
                <el-button type="primary" @click="changeItem()">确 定</el-button>
            </span>
        </el-dialog>
    </div>
    `,
    props: {
        labelWidth: {
            type: String,
            default: '120px',
        },
        ifset: {
            type: Boolean,
            default: true,
        },
        value: {
            type: Array,
            default: [],
        },
    },
    data() {
        var validateRepeatField = (rule, value, callback) => {
            let isExist = common.arrayIndex(this.list, this.ruleForm.field, 'field');
            if(isExist !== -1) {
                callback(new Error('字段变量不能重复！'));
            } else {
                callback();
            }
        }
        return {
            list: this.value,
            keyword: "",
            draggable: {
                handle: '.rank',
                animation: 300,
                forceFallback: true,
            },
            ruleForm: {
                label: "",
                field: "",
                name: "text",
                value: "",
                bind: "el-input",
                type: "",
                format: "",
                valueFormat: "",
            },
            setForm: {},
            setShow: false,
            setIndex: 0,
            rules: {
                label: [
                    { required: true, message: '请填写字段标题', trigger: 'change' },
                ],
                field: [
                    { required: true, message: '请输入字段变量', trigger: 'change' },
                    { min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'change' },
                    { validator: validateRepeatField, trigger: 'change' }
                ],
                name: [
                    { required: true, message: '请选择字段类型', trigger: 'change' },
                ],
            },
            predefineColors: common.predefineColors(),
        }
    },
    methods: {
        /**
         * 添加
         */
        addItem() {
            this.$refs.ruleForm.validate((valid) => {
                if (valid) {
                    this.list.push(JSON.parse(JSON.stringify(this.ruleForm)));
                    this.$refs.ruleForm.resetFields();
                    this.ruleForm = Object.assign({}, this.ruleForm, {label: "", field: "", name: "text", value: "", bind: "el-input", type: "", format: "", valueFormat: ""});
                } else {
                    return false;
                }
            });
        },
        /**
         * 改变
         */
        changeItem() {
            this.$refs.setForm.validate((valid) => {
                if (valid) {
                    this.$set(this.list, this.setIndex, this.setForm);
                    this.setShow = false;
                } else {
                    return false;
                }
            });
        },
        /**
         * 设置
         */
        setItem(item, index) {
            this.setIndex = index;
            this.setForm  = JSON.parse(JSON.stringify(item));
            this.setShow  = true;
        },
        /**
         * 类型
         */
        fieldTypeChange(item) {
            let index = common.arrayIndex(common.formType(), item.name, 'name');
            let formType     = common.formType()[index];
            item.value       = formType.value;
            item.bind        = formType.bind;
            item.type        = formType.type;
            item.format      = formType.format;
            item.valueFormat = formType.valueFormat;
        },
    },
    watch: {
        value(v) {
            this.list = v;
        },
        list(v) {
            this.value = v;
            this.$emit('input', v);
        }
    }
})
/**
 * 参数组件
 */
Vue.component('mk-parameter', {
    template:`
    <div class="mk-parameter">
        <el-button 
            type="primary" 
            size="small" 
            @click="list.unshift({title: '', value: ''})">
            添加参数
        </el-button>
        <el-input 
            style="width:300px" 
            size="small" 
            placeholder="请输入搜索内容" 
            prefix-icon="el-icon-search" 
            v-model="keyword">
        </el-input>
        <el-empty v-if="list.length === 0" description="暂无参数"></el-empty>
        <draggable v-model="list" v-bind="draggable">
            <template
                v-for="(item, index) in list" 
                :key="index">
                <div v-show="item.title.indexOf(keyword) != -1 || item.value.indexOf(keyword) != -1" class="mk-parameter-item">
                    <el-input size="small" v-model="item.title" placeholder="请输入标题" class="title"><template slot="prepend">标题</template></el-input>
                    <el-input size="small" v-model="item.value" placeholder="请输入内容" class="value"><template slot="prepend">内容</template></el-input>
                    <el-button size="mini" class="rank" type="info" icon="el-icon-rank" circle></el-button>
                    <el-button size="mini" type="danger" icon="el-icon-close" circle @click="list.splice(index, 1)"></el-button>
                </div>
            </template>
        </draggable>
    </div>
    `,
    props: {
        value: {
            type: Array,
            default: [],
        },
    },
    data() {
        return {
            list: this.value,
            keyword: "",
            draggable: {
                handle: '.rank',
                animation: 300,
                forceFallback: true,
            },
        }
    },
    watch: {
        value(v) {
            this.list = v;
        },
        list(v) {
            this.value = v;
            this.$emit('input', v);
        }
    }
})
/**
 * 编辑器默认是textarea
 */
Vue.component('mk-editor', {
    template: `
        <div class="mk-editor">
            <el-input type="textarea" v-model="content" :rows="10"></el-input>
        </div>
    `,
    props: {
        value: {
            type: String,
            default: "",
        },
        height: {
            type: Number,
            default: 400,
        },
    },
    data() {
        return {
            content: this.value,
        }
    },
    watch: {
        value(v) {
            this.content = v;
        },
        content(v) {
            this.value = v;
            this.$emit('input', v);
        },
    }
})